Default login shell path on Android devices
Tito
farmatito at tiscali.it
Sun Mar 6 20:49:11 UTC 2011
On Sunday 06 March 2011 18:59:04 Denys Vlasenko wrote:
> On Friday 04 March 2011 00:45, Dudy Kohen wrote:
> > Hi,
> > A lot of "aftermarket" Android developers add busybox to their builds.
> > I have found out that the hardcoded default login shell is not valid
> > in Android and it causes issues with scrips that do not have shebangs.
> > I have sent this to one of the AOSP-based projects and it got
> > accepted, and I thought it would benefit if it existed upstream as
> > well.
> > I know that you do not have Android code as part of your normal
> > source, but this change is controlled by #ifdefs and thus should not
> > affect the resulting code at all if not defined as Android.
> > Thanks,
> > David Kohen
>
> Rob's suggestion to make LIBBB_DEFAULT_LOGIN_SHELL and DEFAULT_SHELL_SHORT_NAME
> configurable sounds better to me.
>
> Moreover, an even better thing we can do here is to use this problem
> as an opportunity to audit and fix the code so that shell name
> can be overridden with $SHELL variable (where applicable: say, su
> shouldn't use it), and by user's default shell.
>
> On android, is $SHELL set correctly? Do users have pw->pw_shell
> which point to correct shell?
>
>
> Let's look at the current code.
>
> $ grep -B3 -r DEFAULT_SHELL .
> ./loginutils/su.c- * is a username that is retrieved via NIS (YP), that doesn't have
> ./loginutils/su.c- * a default shell listed. */
> ./loginutils/su.c- if (!pw->pw_shell || !pw->pw_shell[0])
> ./loginutils/su.c: pw->pw_shell = (char *)DEFAULT_SHELL;
> --
>
> Seems to be ok as-is: normally pw->pw_shell will have correct value.
>
> ./loginutils/adduser.c- }
> ./loginutils/adduser.c-
> ./loginutils/adduser.c- pw.pw_gecos = (char *)"Linux User,,,";
> ./loginutils/adduser.c: pw.pw_shell = (char *)DEFAULT_SHELL;
> --
>
> I doubt you'll want to use adduser on Android
>
> ./loginutils/login.c- change_identity(pw);
> ./loginutils/login.c- shell = pw->pw_shell;
> ./loginutils/login.c- if (!shell || !shell[0])
> ./loginutils/login.c: shell = DEFAULT_SHELL;
> --
>
> Seems to be ok as-is: normally pw->pw_shell will have correct value.
>
> ./util-linux/script.c- }
> ./util-linux/script.c- shell = getenv("SHELL");
> ./util-linux/script.c- if (shell == NULL) {
> ./util-linux/script.c: shell = DEFAULT_SHELL;
> --
>
> Should we try to retrieve current user's shell (getpwuid(getuid())->pw_shell)
> before falling back to DEFAULT_SHELL?
>
> ./miscutils/crond.c- xsetenv("HOME", pas->pw_dir);
> ./miscutils/crond.c-#endif
> ./miscutils/crond.c- /* currently, we use constant one: */
> ./miscutils/crond.c: /*setenv("SHELL", DEFAULT_SHELL, 1); - done earlier */
> --
> ./miscutils/crond.c- }
> ./miscutils/crond.c- }
> ./miscutils/crond.c-
> ./miscutils/crond.c: line->cl_pid = fork_job(user, mailFd, DEFAULT_SHELL, line->cl_cmd);
> --
> ./miscutils/crond.c- /* initgroups, setgid, setuid, and chdir to home or TMPDIR */
> ./miscutils/crond.c- change_user(pas);
> ./miscutils/crond.c- if (DebugOpt) {
> ./miscutils/crond.c: crondlog(LVL5 "child running %s", DEFAULT_SHELL);
> ./miscutils/crond.c- }
> ./miscutils/crond.c- /* crond 3.0pl1-100 puts tasks in separate process groups */
> ./miscutils/crond.c- bb_setpgrp();
> ./miscutils/crond.c: execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_cmd, (char *) NULL);
> ./miscutils/crond.c: crondlog(ERR20 "can't execute '%s' for user %s", DEFAULT_SHELL, user);
> --
> ./miscutils/crond.c-
> ./miscutils/crond.c- xchdir(G.crontab_dir_name);
> ./miscutils/crond.c- //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */
> ./miscutils/crond.c: xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */
> --
>
> Should we try to use $SHELL, then try retrieve user's shell
> before falling back to DEFAULT_SHELL?
>
>
> ./miscutils/crontab.c- /* CHILD - change user and run editor */
> ./miscutils/crontab.c- /* initgroups, setgid, setuid */
> ./miscutils/crontab.c- change_identity(pas);
> ./miscutils/crontab.c: setup_environment(DEFAULT_SHELL,
> --
>
> Should we try to use $SHELL, then try retrieve user's shell
> before falling back to DEFAULT_SHELL?
>
> ./miscutils/conspy.c- char *shell = getenv("SHELL");
> ./miscutils/conspy.c-
> ./miscutils/conspy.c- if (!shell)
> ./miscutils/conspy.c: shell = (char *) DEFAULT_SHELL;
> --
>
> Should we try to retrieve current user's shell (getpwuid(getuid())->pw_shell)
> before falling back to DEFAULT_SHELL?
>
> ./libbb/run_shell.c-
> ./libbb/run_shell.c-#endif
> ./libbb/run_shell.c-
> ./libbb/run_shell.c:/* Run SHELL, or DEFAULT_SHELL if SHELL is "" or NULL.
> --
> ./libbb/run_shell.c- args = xmalloc(sizeof(char*) * (4 + additional_args_cnt));
> ./libbb/run_shell.c-
> ./libbb/run_shell.c- if (!shell || !shell[0])
> ./libbb/run_shell.c: shell = DEFAULT_SHELL;
> --
>
> This looks ok.
>
> ./shell/ash.c- continue;
> ./shell/ash.c- ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
> ./shell/ash.c- ap[1] = cmd;
> ./shell/ash.c: ap[0] = cmd = (char *)DEFAULT_SHELL;
> --
>
> Need to read shell documentation to figure out what standards say.
>
> ./runit/svlogd.c- xmove_fd(fd, 5);
> ./runit/svlogd.c-
> ./runit/svlogd.c-// getenv("SHELL")?
> ./runit/svlogd.c: execl(DEFAULT_SHELL, DEFAULT_SHELL_SHORT_NAME, "-c", ld->processor, (char*) NULL);
> --
>
> Should we try to use $SHELL, then try retrieve user's shell
> before falling back to DEFAULT_SHELL?
>
> ./archival/libarchive/data_extract_to_command.c- close(p[1]);
> ./archival/libarchive/data_extract_to_command.c- xdup2(p[0], STDIN_FILENO);
> ./archival/libarchive/data_extract_to_command.c- signal(SIGPIPE, SIG_DFL);
> ./archival/libarchive/data_extract_to_command.c: execl(DEFAULT_SHELL, DEFAULT_SHELL_SHORT_NAME, "-c", archive_handle->tar__to_command, NULL);
> ./archival/libarchive/data_extract_to_command.c: bb_perror_msg_and_die("can't execute '%s'", DEFAULT_SHELL);
> --
>
> Should we try to use $SHELL, then try retrieve user's shell
> before falling back to DEFAULT_SHELL?
>
> ./networking/ifupdown.c- case -1: /* failure */
> ./networking/ifupdown.c- return 0;
> ./networking/ifupdown.c- case 0: /* child */
> ./networking/ifupdown.c: execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, (char *) NULL, G.my_environ);
> --
>
> Should we try to use $SHELL, then try retrieve user's shell
> before falling back to DEFAULT_SHELL?
>
> ./coreutils/chroot.c- argv -= 2;
> ./coreutils/chroot.c- argv[0] = getenv("SHELL");
> ./coreutils/chroot.c- if (!argv[0]) {
> ./coreutils/chroot.c: argv[0] = (char *) DEFAULT_SHELL;
> --
>
> Should we try to retrieve current user's shell (getpwuid(getuid())->pw_shell)
> before falling back to DEFAULT_SHELL?
>
> --
> ./console-tools/openvt.c- argv--;
> ./console-tools/openvt.c- argv[0] = getenv("SHELL");
> ./console-tools/openvt.c- if (!argv[0])
> ./console-tools/openvt.c: argv[0] = (char *) DEFAULT_SHELL;
> --
>
> Should we try to retrieve current user's shell (getpwuid(getuid())->pw_shell)
> before falling back to DEFAULT_SHELL?
>
>
>
> In short, seems like we can create a helper function and use it in most
> of these locations.
>
> Care to prepare a patch?
>
On android there are no passwd/group files at all
passwd and group structs are created on the fly
from hardcoded values (for system ids) or from
file uids/gids for installed apps
static struct passwd*
android_iinfo_to_passwd( struct passwd *pw,
struct android_id_info *iinfo )
{
pw->pw_name = (char*)iinfo->name;
pw->pw_uid = iinfo->aid;
pw->pw_gid = iinfo->aid;
pw->pw_dir = "/";
pw->pw_shell = "/system/bin/sh";
return pw;
}
/* translate a uid into the corresponding app_<uid>
* passwd structure (sets errno to ENOENT on failure)
*/
static struct passwd*
app_id_to_passwd(uid_t uid, stubs_state_t* state)
{
struct passwd* pw = &state->passwd;
if (uid < AID_APP) {
errno = ENOENT;
return NULL;
}
snprintf( state->app_name_buffer, sizeof state->app_name_buffer,
"app_%u", uid - AID_APP );
pw->pw_name = state->app_name_buffer;
pw->pw_dir = "/data";
pw->pw_shell = "/system/bin/sh";
pw->pw_uid = uid;
pw->pw_gid = uid;
return pw;
}
If somebody is interested in this exotic stuff there is more at:
http://android.git.kernel.org/?p=platform/bionic.git;a=blob;f=libc/bionic/stubs.c;h=a01d64c2f3c8b934586c217e2ad2520922b07a6f;hb=HEAD
Enjoy.
Ciao,
Tito
More information about the busybox
mailing list