From 81f2dbc142bc5bedf19fa1f301ca486d10d127c3 Mon Sep 17 00:00:00 2001 From: Callum Andrew Date: Sat, 7 Jun 2025 14:20:39 +1000 Subject: [PATCH 1/2] fix(scripts/chsh.in): allow passing absolute path to shell chsh first checks for a shell using its absolute path (if it starts with `/`), before checking in `$PREFIX/bin/` --- scripts/chsh.in | 63 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/scripts/chsh.in b/scripts/chsh.in index b74f58e..32702b0 100644 --- a/scripts/chsh.in +++ b/scripts/chsh.in @@ -1,24 +1,58 @@ #!/bin/sh +# shellcheck shell=dash -set -e -u +set -eu -show_usage () { +is_executable_file() { + test -f "$1" -a -x "$1" +} + +show_usage() { echo "usage: chsh [-s shell]" echo "Change the login shell." + echo + if [ "${1:-}" = "login" ]; then + echo "The shell value must be one of following and cannot be 'login':" + else + echo "The shell value must be one of following:" + fi + echo " - Empty value to restore default shell." + echo " - Absolute path to shell starting with a '/'." + echo " - Relative path to shell not starting with a '/' relative to '@TERMUX_PREFIX@/bin'." } -set_shell () { - if [ "$1" = login ]; then - echo "login is not a valid shell" +set_shell() { + if [ -z "${1:-}" ]; then + echo "Restoring default shell" + rm -f "$HOME/.termux/shell" + exit 0 + fi + + if [ "$1" = "login" ]; then + show_usage "login" exit 1 fi - mkdir -p $HOME/.termux - NEW_SHELL=@TERMUX_PREFIX@/bin/$1 - if test -x $NEW_SHELL -a ! -d $NEW_SHELL; then - ln -f -s $NEW_SHELL $HOME/.termux/shell - else - echo "$NEW_SHELL is not an executable file!" + mkdir -p "$HOME/.termux" + + unset NEW_SHELL + case "$1" in + "/"*) NEW_SHELL="$1" ;; + *) NEW_SHELL="@TERMUX_PREFIX@/bin/$1" ;; + esac + + SHELL_TARGET="$(realpath -s "$NEW_SHELL")" + + if ! is_executable_file "$SHELL_TARGET"; then + echo "The shell file '$SHELL_TARGET' is not an executable file." 1>&2 + exit 1 fi + + if [ "$SHELL_TARGET" -ef "@TERMUX_PREFIX@/bin/login" ]; then + echo "The shell file '$SHELL_TARGET' must not point to the '@TERMUX_PREFIX@/bin/login' script." 1>&2 + exit 1 + fi + + ln -sf "$SHELL_TARGET" "$HOME/.termux/shell" } O=`getopt -l help -- hs: "$@"` @@ -26,19 +60,18 @@ eval set -- "$O" while true; do case "$1" in -h|--help) show_usage; exit 0;; - -s) set_shell $2; exit 0;; + -s) set_shell "$2"; exit 0;; --) shift; break;; *) echo Error; show_usage; exit 1;; esac done DEFAULT_SHELL=bash -if [ ! -x @TERMUX_PREFIX@/bin/$DEFAULT_SHELL ]; then DEFAULT_SHELL=sh; fi +if ! is_executable_file "@TERMUX_PREFIX@/bin/$DEFAULT_SHELL"; then DEFAULT_SHELL=sh; fi echo Changing the login shell echo Enter the new value, or press ENTER for the default printf " Login Shell [$DEFAULT_SHELL]: " read shell -if [ -z "$shell" ]; then shell=$DEFAULT_SHELL; fi -set_shell $shell +set_shell "$shell" From 50528670dae323b49d76e3ff3e71b68f6701eb11 Mon Sep 17 00:00:00 2001 From: Callum Andrew Date: Tue, 10 Jun 2025 12:15:17 +1000 Subject: [PATCH 2/2] fix(scripts/login.in): don't canonicalize symlink value also allow shells owned by different effective group IDs --- scripts/login.in | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/scripts/login.in b/scripts/login.in index 2e7aa79..e862089 100644 --- a/scripts/login.in +++ b/scripts/login.in @@ -1,4 +1,18 @@ #!/bin/sh +# shellcheck shell=dash + +is_executable_file() { + test -f "$1" -a -x "$1" +} + +set_default_shell() { + for file in "@TERMUX_PREFIX@/bin/bash" "@TERMUX_PREFIX@/bin/sh" "/system/bin/sh"; do + if is_executable_file "$file"; then + SHELL="$file" + break + fi + done +} if tty >/dev/null 2>&1 && [ $# = 0 ] && [ ! -f ~/.hushlogin ] && [ -z "$TERMUX_HUSHLOGIN" ]; then # Use user defined dynamic motd file if it exists @@ -19,17 +33,24 @@ if tty >/dev/null 2>&1 && [ $# = 0 ] && [ -f @TERMUX_PREFIX@/etc/motd-playstore printf '\033[0;31m'; cat @TERMUX_PREFIX@/etc/motd-playstore; printf '\033[0m' fi -if [ -G ~/.termux/shell ]; then - export SHELL="`realpath ~/.termux/shell`" -else - for file in @TERMUX_PREFIX@/bin/bash @TERMUX_PREFIX@/bin/sh /system/bin/sh; do - if [ -x $file ]; then - export SHELL=$file - break - fi - done +unset SHELL +SHELL_FILE=~/.termux/shell + +if [ -L "$SHELL_FILE" ]; then + # Set the symlink's value as the shell target. + SHELL_TARGET="$(readlink "$SHELL_FILE")" + if is_executable_file "$SHELL_TARGET" && + [ ! "$SHELL_TARGET" -ef "@TERMUX_PREFIX@/bin/login" ]; then + SHELL="$SHELL_TARGET" + fi fi +if [ -z "${SHELL:-}" ]; then + set_default_shell +fi + +export SHELL + # TERMUX_APP_PACKAGE_MANAGER should be exported by termux-app v0.119.0+ itself if [ -z "${TERMUX_APP_PACKAGE_MANAGER-}" ]; then if { [ -n "$(command -v dpkg)" ] && dpkg --compare-versions "$TERMUX_VERSION" lt 0.119.0; } || # apt