On Tue, Jul 30, 2013 at 03:55:45PM -0400, dwalsh@xxxxxxxxxx wrote: > From: Dan Walsh <dwalsh@xxxxxxxxxx> > > Openshift wants to have their gears stuck into a container when they login > to the system. virt-login-shell will join a running gear with the username of > the person running it, or attempt to start the container if it is not running. > (Currently containers do not exist if they are not running, so I can not test > this feature. But the code is there). > > This tool needs to be setuid since joining a container (nsjoin) requires privs. > The root user is not allowed to execute this command. When this tool is > run by a normal user it will only join the "users" container. > > Only users who are listed as valid_users in /etc/libvirt/virt-login-shell.conf > are allowed to join containers using this tool. By default no users are allowed. > --- > +static ssize_t nfdlist = 0; > +static int *fdlist = NULL; > +static const char *conf_file = SYSCONFDIR "/libvirt/virt-login-shell.conf"; > + > +static void virLoginShellFini(virConnectPtr conn, virDomainPtr dom) > +{ > + size_t i; > + > + for (i = 0; i < nfdlist; i++) > + VIR_FORCE_CLOSE(fdlist[i]); > + VIR_FREE(fdlist); > + nfdlist = 0; > + if (dom) > + virDomainFree(dom); > + if (conn) > + virConnectClose(conn); There are lots of tabs used for indent here and later in this file. Please check with 'make syntax-check'. > +static int virLoginShellAllowedUser(virConfPtr conf, > + uid_t uid, > + gid_t gid, > + const char *name) > +{ > + virConfValuePtr p; > + int ret = -1; > + char *ptr = NULL; > + size_t i; > + gid_t *groups = NULL; > + char *gname = NULL; > + > + p = virConfGetValue(conf, "allowed_users"); > + if (p && p->type == VIR_CONF_LIST) { > + virConfValuePtr pp; > + > + /* Calc length and check items */ > + for (pp = p->list; pp; pp = pp->next) { > + if (pp->type != VIR_CONF_STRING) { > + virReportSystemError(EINVAL, "%s", _("shell must be a list of strings\n")); > + goto cleanup; > + } else { > + /* > + If string begins with a % this indicates a linux group. > + Check to see if the user is in the Linux Group. > + */ > + if (pp->str[0] == '%') { > + ptr = &pp->str[1]; > + if (!ptr) > + continue; > + if (virGetGroupList(uid, gid, &groups) < 0) { > + goto cleanup; > + } > + for (i = 0; groups[i]; i++) { > + if (!(gname = virGetGroupName(groups[i]))) > + continue; > + if (fnmatch(ptr, gname, 0) == 0) { > + ret = 0; > + goto cleanup; > + } > + VIR_FREE(gname); > + } > + VIR_FREE(groups); > + continue; > + } > + if (fnmatch(pp->str, name, 0) == 0) { > + ret = 0; > + goto cleanup; > + } > + } > + } > + } > + virReportSystemError(EPERM, _("%s not listed as an allowed_users in %s"), name, conf_file); > + errno = EPERM; No need to set errno if you using virReportSystemError(). > +cleanup: > + VIR_FREE(gname); > + VIR_FREE(groups); > + return ret; > +} > + > +int > +main(int argc, char **argv) > +{ > + > + struct option opt[] = { > + {"help", no_argument, NULL, 'h'}, > + {NULL, 0, NULL, 0} > + }; > + virReportSystemError(1, "%s %d %s", "Test1", argc, argv[0]); Accidental debug line left in I presume > + if (virInitialize() < 0) { > + fprintf(stderr, _("Failed to initialize libvirt Error Handling")); > + return EXIT_FAILURE; > + } > + virReportSystemError(EINVAL, "%s", "Test2"); And here > + > + if (virErrorInitialize() < 0) { > + fprintf(stderr, _("Failed to initialize libvirt Error Handling")); > + return EXIT_FAILURE; > + } Actually no need to call virErrorInitialize() - virInitialize takes care of that for you > + if (uid == 0) { > + virReportSystemError(EPERM, _("%s must be run by non root users"), progname); > + > + errno = EPERM; No need to set errno. > + if (virFork(&cpid) < 0) > + goto cleanup; > + > + if (cpid == 0) { > + gid_t *groups = NULL; > + int ngroups; > + pid_t ccpid; > + > + /* Fork once because we don't want to affect > + * virt-login-shell's namespace itself > + */ > + if (virSetUIDGID(0, 0, NULL, 0) < 0) > + return EXIT_FAILURE; > + > + if (virDomainLxcEnterSecurityLabel(secmodel, > + seclabel, > + NULL, > + 0) < 0) > + return EXIT_FAILURE; > + > + if (nfdlist > 0) { > + if (virDomainLxcEnterNamespace(dom, > + nfdlist, > + fdlist, > + NULL, > + NULL, > + 0) < 0) > + return EXIT_FAILURE; > + } > + > + if ((ngroups = virGetGroupList(uid, gid, &groups)) < 0) > + return EXIT_FAILURE; virGetGroupList isn't safe to call after fork(). Need to move it earlier in this function. > + > + ret = virSetUIDGID(uid, gid, groups, ngroups); > + VIR_FREE(groups); > + if (ret < 0) > + return EXIT_FAILURE; > + > + if (virFork(&ccpid) < 0) > + return EXIT_FAILURE; > + > + if (ccpid == 0) { > + if (chdir(homedir) < 0) { > + virReportSystemError(errno, _("Unable chdir(%s)"), homedir); > + return EXIT_FAILURE; > + } > + if (execv(shargv[0], (char *const*) shargv) < 0) { > + virReportSystemError(errno, _("Unable exec shell %s"), shargv[0]); > + return -errno; > + } > + } > + return virProcessWait(ccpid, &status2); > + } > + ret = virProcessWait(cpid, &status); > + Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list