It will be useful in the future to be able to set ownership on other files which Open vSwitch creates. Allowing the specification of such ownership using the standard user:group notation by the user is desirable. So move the code which parses that information up one level to be used from other modules.
Signed-off-by: Aaron Conole <acon...@redhat.com> --- lib/daemon-unix.c | 120 ++++++++++++++++++++++++++++++++++-------------------- lib/daemon.h | 1 + 2 files changed, 77 insertions(+), 44 deletions(-) diff --git a/lib/daemon-unix.c b/lib/daemon-unix.c index 182f76b..62afceb 100644 --- a/lib/daemon-unix.c +++ b/lib/daemon-unix.c @@ -926,72 +926,68 @@ enlarge_buffer(char **buf, size_t *sizep) return false; } -/* Parse and sanity check user_spec. - * - * If successful, set global variables 'uid' and 'gid' - * with the parsed results. Global variable 'user' - * will be pointing to a string that stores the name - * of the user to be switched into. - * - * Also set 'switch_to_new_user' to true, The actual - * user switching is done as soon as daemonize_start() - * is called. I/O access before calling daemonize_start() - * will still be with root's credential. */ -void -daemon_set_new_user(const char *user_spec) +int +get_owners_from_str(const char *user_spec, uid_t *uid, char **user, + gid_t *gid, bool validate_user_group) { char *pos = strchr(user_spec, ':'); size_t init_bufsize, bufsize; init_bufsize = get_sysconf_buffer_size(); - uid = getuid(); - gid = getgid(); - - if (geteuid() || uid) { - VLOG_FATAL("%s: only root can use --user option", pidfile); - } - user_spec += strspn(user_spec, " \t\r\n"); + size_t len = pos ? pos - user_spec : strlen(user_spec); - char *buf; + + char *buf = NULL; struct passwd pwd, *res; int e; bufsize = init_bufsize; buf = xmalloc(bufsize); + char *user_search = NULL; if (len) { - user = xmemdup0(user_spec, len); - - while ((e = getpwnam_r(user, &pwd, buf, bufsize, &res)) == ERANGE) { + user_search = xmemdup0(user_spec, len); + while ((e = getpwnam_r(user_search, &pwd, buf, bufsize, &res)) == ERANGE) { if (!enlarge_buffer(&buf, &bufsize)) { break; } } if (e != 0) { - VLOG_FATAL("%s: Failed to retrive user %s's uid (%s), aborting.", - pidfile, user, ovs_strerror(e)); + VLOG_ERR("%s: Failed to retrive user %s's uid (%s), aborting.", + pidfile, user_search, ovs_strerror(e)); + goto release; } } else { /* User name is not specified, use current user. */ - while ((e = getpwuid_r(uid, &pwd, buf, bufsize, &res)) == ERANGE) { + while ((e = getpwuid_r(getuid(), &pwd, buf, bufsize, &res)) == ERANGE) { if (!enlarge_buffer(&buf, &bufsize)) { break; } } if (e != 0) { - VLOG_FATAL("%s: Failed to retrive current user's name " - "(%s), aborting.", pidfile, ovs_strerror(e)); + VLOG_ERR("%s: Failed to retrive current user's name " + "(%s), aborting.", pidfile, ovs_strerror(e)); + goto release; } - user = xstrdup(pwd.pw_name); + user_search = xstrdup(pwd.pw_name); } - uid = pwd.pw_uid; - gid = pwd.pw_gid; + if (user) + *user = user_search; + + if (uid) + *uid = pwd.pw_uid; + + if (gid) + *gid = pwd.pw_gid; + free(buf); + buf = NULL; if (pos) { + gid_t tmpgid = pwd.pw_gid; char *grpstr = pos + 1; grpstr += strspn(grpstr, " \t\r\n"); @@ -1008,30 +1004,66 @@ daemon_set_new_user(const char *user_spec) } if (e) { - VLOG_FATAL("%s: Failed to get group entry for %s, " - "(%s), aborting.", pidfile, grpstr, - ovs_strerror(e)); + VLOG_ERR("%s: Failed to get group entry for %s, " + "(%s), aborting.", pidfile, grpstr, + ovs_strerror(e)); + goto release; } - if (gid != grp.gr_gid) { + if (tmpgid != grp.gr_gid) { char **mem; for (mem = grp.gr_mem; *mem; ++mem) { - if (!strcmp(*mem, user)) { + if (!strcmp(*mem, user_search)) { break; } } - if (!*mem) { - VLOG_FATAL("%s: Invalid --user option %s (user %s is " - "not in group %s), aborting.", pidfile, - user_spec, user, grpstr); + if (!*mem && validate_user_group) { + VLOG_ERR("%s: Invalid user str %s (user %s is " + "not in group %s).", pidfile, user_spec, + user_search, grpstr); + e = EINVAL; + goto release; } - gid = grp.gr_gid; + if (gid) + *gid = grp.gr_gid; } - free(buf); } } - switch_user = true; + release: + free(buf); + if(e) { + free(user_search); + } + return e; +} + +/* Parse and sanity check user_spec. + * + * If successful, set global variables 'uid' and 'gid' + * with the parsed results. Global variable 'user' + * will be pointing to a string that stores the name + * of the user to be switched into. + * + * Also set 'switch_to_new_user' to true, The actual + * user switching is done as soon as daemonize_start() + * is called. I/O access before calling daemonize_start() + * will still be with root's credential. */ +void +daemon_set_new_user(const char *user_spec) +{ + uid = getuid(); + gid = getgid(); + + if (geteuid() || uid) { + VLOG_FATAL("%s: only root can use --user option", pidfile); + } + + if (!get_owners_from_str(user_spec, &uid, &user, &gid, true)) { + switch_user = true; + } else { + VLOG_FATAL("Failed --user with option %s. aborting.", user_spec); + } } diff --git a/lib/daemon.h b/lib/daemon.h index 4990415..8742aa8 100644 --- a/lib/daemon.h +++ b/lib/daemon.h @@ -83,6 +83,7 @@ void daemon_set_monitor(void); void set_no_chdir(void); void ignore_existing_pidfile(void); pid_t read_pidfile(const char *name); +int get_owners_from_str(const char *user_spec, uid_t *uid, char **user, gid_t *gid, bool validate_user_group); #else #define DAEMON_OPTION_ENUMS \ OPT_DETACH, \ -- 2.6.1.133.gf5b6079 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev