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