Quoting Christian Seiler (christ...@iwakd.de):
> If no command is specified, and using getpwuid() to determine the login
> shell fails, try to spawn a process that executes the utility 'getent'.
> getpwuid() may fail because of incompatibilities between the NSS
> implementations on the host and in the container.
> 
> Signed-off-by: Christian Seiler <christ...@iwakd.de>

Acked-by: Serge E. Hallyn <serge.hal...@ubuntu.com>

One comment below - I'll just change it after applying yours if you
don't mind.

> ---
>  src/lxc/attach.c     |  154 
> ++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/lxc/attach.h     |    2 +
>  src/lxc/lxc_attach.c |   18 +++++-
>  3 files changed, 172 insertions(+), 2 deletions(-)
> 
> diff --git a/src/lxc/attach.c b/src/lxc/attach.c
> index af3d7a0..d1b3b0a 100644
> --- a/src/lxc/attach.c
> +++ b/src/lxc/attach.c
> @@ -32,7 +32,9 @@
>  #include <sys/prctl.h>
>  #include <sys/mount.h>
>  #include <sys/syscall.h>
> +#include <sys/wait.h>
>  #include <linux/unistd.h>
> +#include <pwd.h>
>  
>  #if !HAVE_DECL_PR_CAPBSET_DROP
>  #define PR_CAPBSET_DROP 24
> @@ -275,3 +277,155 @@ int lxc_attach_drop_privs(struct lxc_proc_context_info 
> *ctx)
>  
>       return 0;
>  }
> +
> +char *lxc_attach_getpwshell(uid_t uid)
> +{
> +     /* local variables */
> +     pid_t pid;
> +     int pipes[2];
> +     int ret;
> +     int fd;
> +     char *result = NULL;
> +
> +     /* we need to fork off a process that runs the
> +      * getent program, and we need to capture its
> +      * output, so we use a pipe for that purpose
> +      */
> +     ret = pipe(pipes);
> +     if (ret < 0)
> +             return NULL;
> +
> +     pid = fork();
> +     if (pid < 0) {
> +             close(pipes[0]);
> +             close(pipes[1]);
> +             return NULL;
> +     }
> +
> +     if (pid) {
> +             /* parent process */
> +             FILE *pipe_f;
> +             char *line = NULL;
> +             size_t line_bufsz = 0;
> +             int found = 0;
> +             int status;
> +
> +             close(pipes[1]);
> +
> +             pipe_f = fdopen(pipes[0], "r");
> +             while (getline(&line, &line_bufsz, pipe_f) != -1) {
> +                     char *token;
> +                     char *saveptr = NULL;
> +                     long value;
> +                     char *endptr = NULL;
> +                     int i;
> +
> +                     /* if we already found something, just continue
> +                      * to read until the pipe doesn't deliver any more
> +                      * data, but don't modify the existing data
> +                      * structure
> +                      */
> +                     if (found)
> +                             continue;
> +
> +                     /* trim line on the right hand side */
> +                     for (i = strlen(line); line && i > 0 && (line[i - 1] == 
> '\n' || line[i - 1] == '\r'); --i)
> +                             line[i - 1] = '\0';
> +
> +                     /* split into tokens: first user name */
> +                     token = strtok_r(line, ":", &saveptr);
> +                     if (!token)
> +                             continue;
> +                     /* next: dummy password field */
> +                     token = strtok_r(NULL, ":", &saveptr);
> +                     if (!token)
> +                             continue;
> +                     /* next: user id */
> +                     token = strtok_r(NULL, ":", &saveptr);
> +                     value = token ? strtol(token, &endptr, 10) : 0;
> +                     if (!token || !endptr || *endptr || value == LONG_MIN 
> || value == LONG_MAX)
> +                             continue;
> +                     /* dummy sanity check: user id matches */
> +                     if ((uid_t) value != uid)
> +                             continue;
> +                     /* skip fields: gid, gecos, dir, go to next field 
> 'shell' */
> +                     for (i = 0; i < 4; i++) {
> +                             token = strtok_r(NULL, ":", &saveptr);
> +                             if (!token)
> +                                     break;
> +                     }
> +                     if (!token)
> +                             continue;

        If the sanity check below now fails, we ill leak result.
        Not very important since we're about to exec, but I'll add
        a if (result) free(result); right here.

> +                     result = strdup(token);
> +
> +                     /* sanity check that there are no fields after that */
> +                     token = strtok_r(NULL, ":", &saveptr);
> +                     if (token)
> +                             continue;
> +
> +                     found = 1;
> +             }

------------------------------------------------------------------------------
Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester  
Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the  
endpoint security space. For insight on selecting the right partner to 
tackle endpoint security challenges, access the full report. 
http://p.sf.net/sfu/symantec-dev2dev
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to