| Summary: | adduser without -s (shell) creates invalid /etc/passwd entry | ||
|---|---|---|---|
| Product: | Busybox | Reporter: | Jonathon Reinhart <Jonathon.Reinhart> |
| Component: | Other | Assignee: | unassigned |
| Status: | RESOLVED FIXED | ||
| Severity: | normal | CC: | busybox-cvs, dennis.schridde |
| Priority: | P5 | ||
| Version: | 1.22.x | ||
| Target Milestone: | --- | ||
| Hardware: | All | ||
| OS: | Linux | ||
| Host: | Target: | ||
| Build: | |||
| Attachments: | Patch to fix this issue | ||
|
Description
Jonathon Reinhart
2016-01-05 13:40:17 UTC
I can still confirm this in Alpine Linux 3.5 with busybox v1.25.1: ``` $ docker run -ti alpine:3.5 /bin/sh / # addgroup -g 1000 xgroup / # adduser -u 1012 -G xgroup -h /home/user -D xuser / # grep xuser /etc/passwd xuser:x:1012:1000:Linux User,,,:/home/user:,,,:/home/ / # grep another /etc/passwd another-user:x:1013:1000:Linux User,,,:/home/another:/sbin/halt ``` I can still confirm this in Alpine Linux 3.5 with busybox v1.25.1: ``` $ docker run -ti alpine:3.5 /bin/sh / # busybox | head -n1 BusyBox v1.25.1 (2016-10-26 16:15:20 GMT) multi-call binary. / # addgroup -g 1000 xgroup / # adduser -u 1012 -G xgroup -h /home/user -D xuser / # grep xuser /etc/passwd xuser:x:1012:1000:Linux User,,,:/home/user:,,,:/home/ / # grep another /etc/passwd another-user:x:1013:1000:Linux User,,,:/home/another:/sbin/halt ``` adduser.c:
pw.pw_shell = (char *)get_shell_name();
get_shell_name(void)
{
struct passwd *pw;
char *shell;
shell = getenv("SHELL");
if (shell && shell[0])
return shell;
pw = getpwuid(getuid());
if (pw && pw->pw_shell && pw->pw_shell[0])
return pw->pw_shell;
return DEFAULT_SHELL;
}
DEFAULT_SHELL is "/bin/sh"
What you see can be explained by $SHELL or current user's shell being set to a weird value.
(In reply to Denys Vlasenko from comment #3) `$SHELL` is not set at all: ``` # docker run -ti alpine:3.5 /bin/sh / # env HOSTNAME=59df3c3f58de SHLVL=1 HOME=/root TERM=xterm PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PWD=/ ``` Interestingly, I cannot reproduce this with the busybox:1.25.1-musl container image: ``` $ docker run -ti busybox:1.25.1-musl /bin/sh / # busybox | head -n1 BusyBox v1.25.1 (2016-10-07 18:16:05 UTC) multi-call binary. / # addgroup -g 1000 xgroup / # adduser -u 1012 -G xgroup -h /home/user -D xuser / # grep xuser /etc/passwd xuser:x:1012:1000:Linux User,,,:/home/user:/bin/sh / # adduser -u 1013 -G xgroup -h /home/another -D another-user / # grep another /etc/passwd another-user:x:1013:1000:Linux User,,,:/home/another:/bin/sh ``` (In reply to Dennis Schridde from comment #4) > `$SHELL` is not set at all: I did not say that $SHELL is set. Look at the code in comment #3. If $SHELL is not set, what does it do? It uses current user's shell (if pwd database is accessible and if shell is not empty). I guess that's what is being used in your case. (In reply to Denys Vlasenko from comment #6) Thanks for clarifying this. /etc/passwd appears to be correct, though. Also I cannot reproduce this in the official Busybox Docker image, but only with the version used in Alpine Linux. Thus I think this bug can be closed now, unless Jonathon Reinhart or someone else can still reproduce it. The downstream bugreport for Alpine Linux lives at: https://bugs.alpinelinux.org/issues/5083 My original inquiry was "What was broken, and when/where did it get fixed?" I was already aware that it appeared to be fixed by v1.24.1. Considering we still don't know what exactly was broken, and that https://bugs.alpinelinux.org/issues/5083 is still without a real cause, I'm inclined to leave this open until we've figured it out. Created attachment 7926 [details]
Patch to fix this issue
This is a bug caused by the fact that getpwnam(3) returns a pointer to static data and is used twice in adduser.c
1. Indirectly by get_shell_name()
2. Directly by passwd_study()
This causes the getpwnam(3) call in passwd_study() to "overwrite" the memory location `get_shell_name()` returns a pointer two. There are obviously a variety of ways to address this issue (e.g. making get_shell_name() use getpwnam_r). However, the most simple fix (which also seems to be used elsewhere) is using xstrdup() on the return value of get_shell_name().
Fixed in git, thanks! |