[libvirt] [PATCH 08/10] virt-login-shell: use single instead of double fork

John Ferlan jferlan at redhat.com
Wed Mar 5 13:57:19 UTC 2014


Coverity has found an issue (NEGATIVE_RETURNS)

The 'nfdlist' is the culprit.

> diff --git a/tools/virt-login-shell.c b/tools/virt-login-shell.c
> index 666facf..75a5223 100644
> --- a/tools/virt-login-shell.c
> +++ b/tools/virt-login-shell.c
> @@ -41,24 +41,8 @@
>  #include "vircommand.h"
>  #define VIR_FROM_THIS VIR_FROM_NONE
> 
> -static ssize_t nfdlist;
> -static int *fdlist;
>  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);
> -}
> -
>  static int virLoginShellAllowedUser(virConfPtr conf,
>                                      const char *name,
>                                      gid_t *groups)
> @@ -187,7 +171,6 @@ main(int argc, char **argv)
>      pid_t cpid;
>      int ret = EXIT_FAILURE;
>      int status;
> -    int status2;
>      uid_t uid = getuid();
>      gid_t gid = getgid();
>      char *name = NULL;
> @@ -201,6 +184,10 @@ main(int argc, char **argv)
>      int longindex = -1;
>      int ngroups;
>      gid_t *groups = NULL;
> +    ssize_t nfdlist = 0;
> +    int *fdlist = NULL;
> +    int openmax;
> +    size_t i;
> 
>      struct option opt[] = {
>          {"help", no_argument, NULL, 'h'},
> @@ -298,6 +285,13 @@ main(int argc, char **argv)
>          }
>      }
> 
> +    openmax = sysconf(_SC_OPEN_MAX);
> +    if (openmax < 0) {
> +        virReportSystemError(errno,  "%s",
> +                             _("sysconf(_SC_OPEN_MAX) failed"));
> +        goto cleanup;
> +    }
> +
>      if ((nfdlist = virDomainLxcOpenNamespace(dom, &fdlist, 0)) < 0)
>          goto cleanup;


(36) Event negative_return_fn: 	Function "virDomainLxcOpenNamespace(dom,
&fdlist, 0U)" returns a negative number. [details]
(37) Event var_assign: 	Assigning: signed variable "nfdlist" =
"virDomainLxcOpenNamespace".
(38) Event cond_true: 	Condition "(nfdlist =
virDomainLxcOpenNamespace(dom, &fdlist, 0)) < 0", taking true branch
Also see events: 	[negative_returns]


>      if (VIR_ALLOC(secmodel) < 0)
> @@ -308,76 +302,52 @@ main(int argc, char **argv)
>          goto cleanup;
>      if (virDomainGetSecurityLabel(dom, seclabel) < 0)
>          goto cleanup;
> +    if (virSetUIDGID(0, 0, NULL, 0) < 0)
> +        goto cleanup;
> +    if (virDomainLxcEnterSecurityLabel(secmodel, seclabel, NULL, 0) < 0)
> +        goto cleanup;
> +    if (nfdlist > 0 &&
> +        virDomainLxcEnterNamespace(dom, nfdlist, fdlist, NULL, NULL, 0) < 0)
> +        goto cleanup;
> +    if (virSetUIDGID(uid, gid, groups, ngroups) < 0)
> +        goto cleanup;
> +    if (chdir(homedir) < 0) {
> +        virReportSystemError(errno, _("Unable to chdir(%s)"), homedir);
> +        goto cleanup;
> +    }
> 
> -    /* Fork once because we don't want to affect virt-login-shell's
> -     * namespace itself.  FIXME: is this necessary?
> -     */
> +    /* A fork is required to create new process in correct pid namespace.  */
>      if ((cpid = virFork()) < 0)
>          goto cleanup;
> 
>      if (cpid == 0) {
> -        pid_t ccpid;
> -
> -        int openmax = sysconf(_SC_OPEN_MAX);
> -        int fd;
> +        int tmpfd;
> 
> -        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;
> -        }
> -
> -        ret = virSetUIDGID(uid, gid, groups, ngroups);
> -        VIR_FREE(groups);
> -        if (ret < 0)
> -            return EXIT_FAILURE;
> -
> -        if (openmax < 0) {
> -            virReportSystemError(errno,  "%s",
> -                                 _("sysconf(_SC_OPEN_MAX) failed"));
> -            return EXIT_FAILURE;
> -        }
> -        for (fd = 3; fd < openmax; fd++) {
> -            int tmpfd = fd;
> +        for (i = 3; i < openmax; i++) {
> +            tmpfd = i;
>              VIR_MASS_CLOSE(tmpfd);
>          }
> -
> -        /* A fork is required to create new process in correct pid
> -         * namespace.  */
> -        if ((ccpid = virFork()) < 0)
> +        if (execv(shargv[0], (char *const*) shargv) < 0) {
> +            virReportSystemError(errno, _("Unable to exec shell %s"),
> +                                 shargv[0]);
>              return EXIT_FAILURE;
> -
> -        if (ccpid == 0) {
> -            if (chdir(homedir) < 0) {
> -                virReportSystemError(errno, _("Unable to chdir(%s)"), homedir);
> -                return EXIT_FAILURE;
> -            }
> -            if (execv(shargv[0], (char *const*) shargv) < 0) {
> -                virReportSystemError(errno, _("Unable to exec shell %s"),
> -                                     shargv[0]);
> -                return EXIT_FAILURE;
> -            }
>          }
> -        return virProcessWait(ccpid, &status2, true);
> +        return EXIT_SUCCESS;
>      }
> -    ret = virProcessWait(cpid, &status, true);
> +
> +    if (virProcessWait(cpid, &status, true) < 0)
> +        goto cleanup;
> +    ret = EXIT_SUCCESS;
> 
>  cleanup:
> +    for (i = 0; i < nfdlist; i++)
> +        VIR_FORCE_CLOSE(fdlist[i]);

(41) Event negative_returns: 	Using unsigned variable "nfdlist" in a
loop exit condition.
Also see events: 	[negative_return_fn][var_assign]



> +    VIR_FREE(fdlist);
>      virConfFree(conf);
> -    virLoginShellFini(conn, dom);
> +    if (dom)
> +        virDomainFree(dom);
> +    if (conn)
> +        virConnectClose(conn);
>      virStringFreeList(shargv);
>      VIR_FREE(name);
>      VIR_FREE(homedir);
> 




More information about the libvir-list mailing list