[PATCH] hush: allow hush to run embedded scripts

Denys Vlasenko vda.linux at googlemail.com
Tue Nov 27 15:14:30 UTC 2018


Applied, thanks!
On Tue, Nov 27, 2018 at 3:34 PM Ron Yorston <rmy at pobox.com> wrote:
>
> Embedded scripts require a shell to be present in the BusyBox
> binary.  Allow either ash or hush to be used for this purpose.
> If both are enabled ash takes precedence.
>
> The size of the binary is unchanged in the default configuration:
> both ash and hush are present but support for embedded scripts
> isn't compiled into hush.
>
> Signed-off-by: Ron Yorston <rmy at pobox.com>
> ---
>  archival/libarchive/Kbuild.src |  2 +-
>  docs/embedded-scripts.txt      | 21 ++++++++-------------
>  include/libbb.h                |  5 +++++
>  libbb/appletlib.c              |  8 +++++++-
>  scripts/embedded_scripts       |  8 ++++++++
>  scripts/gen_build_files.sh     |  2 +-
>  shell/Config.src               | 14 ++++++++++++++
>  shell/ash.c                    | 16 +---------------
>  shell/hush.c                   | 16 ++++++++++++++++
>  util-linux/nologin.c           |  2 +-
>  10 files changed, 62 insertions(+), 32 deletions(-)
>
> diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src
> index 12e66a88b..d2f284b08 100644
> --- a/archival/libarchive/Kbuild.src
> +++ b/archival/libarchive/Kbuild.src
> @@ -91,7 +91,7 @@ lib-$(CONFIG_FEATURE_SEAMLESS_LZMA)     += open_transformer.o decompress_unlzma.
>  lib-$(CONFIG_FEATURE_SEAMLESS_XZ)       += open_transformer.o decompress_unxz.o
>  lib-$(CONFIG_FEATURE_COMPRESS_USAGE)    += open_transformer.o decompress_bunzip2.o
>  lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += open_transformer.o decompress_bunzip2.o
> -lib-$(CONFIG_ASH_EMBEDDED_SCRIPTS)      += open_transformer.o decompress_bunzip2.o
> +lib-$(CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS) += open_transformer.o decompress_bunzip2.o
>
>  ifneq ($(lib-y),)
>  lib-y += $(COMMON_FILES)
> diff --git a/docs/embedded-scripts.txt b/docs/embedded-scripts.txt
> index 1b0c5b591..7a273d698 100644
> --- a/docs/embedded-scripts.txt
> +++ b/docs/embedded-scripts.txt
> @@ -3,13 +3,9 @@ Embedded Shell Scripts in BusyBox
>
>  BusyBox allows applets to be implemented as shell scripts.  Since
>  this obviously requires a shell to interpret the scripts the feature
> -depends on having a shell (specifically, ash) built into the binary.
> -Support for embedded scripts also has to be enabled.
> -
> -To embed scripts in BusyBox you must enable these configuration options:
> -
> -   ASH
> -   ASH_EMBEDDED_SCRIPTS
> +depends on having a shell built into the binary.  Either ash or hush
> +will do.  If both are present ash will be used.  Support for embedded
> +scripts also has to be enabled.
>
>  It's unlikely that your applet will be implemented as a pure shell
>  script:  it will probably need some external commands.  If these are
> @@ -75,10 +71,9 @@ code for the native applet:
>
>  The only difference is that the applet is specified as being of type
>  APPLET_SCRIPTED.  It would also be useful to include details of any
> -dependencies the script has.  We can assume that ash is available.
> -No external commands are used by our mu script, but it does depend on
> -optional shell features.  We can ensure these are selected by adding
> -this to the configuration:
> +dependencies the script has.  No external commands are used by our mu
> +script, but it does depend on optional shell features.  We can ensure
> +these are selected by adding this to the configuration:
>
>  //config:config MU_DEPENDENCIES
>  //config:      bool "Enable dependencies for mu"
> @@ -87,8 +82,8 @@ this to the configuration:
>  //config:      select ASH_RANDOM_SUPPORT
>  //config:      select FEATURE_SH_MATH
>  //config:      help
> -//config:      mu is implemented as a shell script. It requires ash
> -//config:      support for $RANDOM and arithmetic.
> +//config:      mu is implemented as a shell script. It requires support
> +//config:      for $RANDOM and arithmetic.
>
>  The configuration data should be placed in a C file in an appropriate
>  subdirectory.  There isn't any C code, though!  In this case the file
> diff --git a/include/libbb.h b/include/libbb.h
> index ebd090e18..b560cc2eb 100644
> --- a/include/libbb.h
> +++ b/include/libbb.h
> @@ -1348,6 +1348,11 @@ int ash_main(int argc, char** argv)
>                 MAIN_EXTERNALLY_VISIBLE
>  #endif
>  ;
> +int hush_main(int argc, char** argv)
> +#if ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH
> +               MAIN_EXTERNALLY_VISIBLE
> +#endif
> +;
>  /* If shell needs them, they exist even if not enabled as applets */
>  int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE);
>  int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE);
> diff --git a/libbb/appletlib.c b/libbb/appletlib.c
> index a79a37efb..cd09b620c 100644
> --- a/libbb/appletlib.c
> +++ b/libbb/appletlib.c
> @@ -50,7 +50,7 @@
>
>  #include "usage_compressed.h"
>
> -#if ENABLE_ASH_EMBEDDED_SCRIPTS
> +#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS
>  # define DEFINE_SCRIPT_DATA 1
>  # include "embedded_scripts.h"
>  #else
> @@ -774,7 +774,13 @@ int scripted_main(int argc UNUSED_PARAM, char **argv)
>  {
>         int script = find_script_by_name(applet_name);
>         if (script >= 0)
> +#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH
>                 exit(ash_main(-script - 1, argv));
> +#elif ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH
> +               exit(hush_main(-script - 1, argv));
> +#else
> +               return 1;
> +#endif
>         return 0;
>  }
>
> diff --git a/scripts/embedded_scripts b/scripts/embedded_scripts
> index 86ad44d1d..aa7bf3e8a 100755
> --- a/scripts/embedded_scripts
> +++ b/scripts/embedded_scripts
> @@ -1,5 +1,7 @@
>  #!/bin/sh
>
> +. ./.config || exit 1
> +
>  target="$1"
>  custom_loc="$2"
>  applet_loc="$3"
> @@ -8,6 +10,12 @@ test "$target" || exit 1
>  test "$SED" || SED=sed
>  test "$DD" || DD=dd
>
> +if [ x"$CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS" != x"y" ]
> +then
> +       printf '#define NUM_SCRIPTS 0\n' >"$target"
> +       exit 0
> +fi
> +
>  # Some people were bitten by their system lacking a (proper) od
>  od -v -b </dev/null >/dev/null
>  if test $? != 0; then
> diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh
> index 362632df3..92de681ac 100755
> --- a/scripts/gen_build_files.sh
> +++ b/scripts/gen_build_files.sh
> @@ -25,7 +25,7 @@ custom_scripts()
>         then
>                 for i in $(cd "$custom_loc"; ls * 2>/dev/null)
>                 do
> -                       printf "APPLET_SCRIPTED(%s, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, scripted)\n" $i;
> +                       printf "IF_FEATURE_SH_EMBEDDED_SCRIPTS(APPLET_SCRIPTED(%s, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, scripted))\n" $i;
>                 done
>         fi
>  }
> diff --git a/shell/Config.src b/shell/Config.src
> index 959d3cb42..bc7218fe5 100644
> --- a/shell/Config.src
> +++ b/shell/Config.src
> @@ -161,6 +161,20 @@ config FEATURE_SH_HISTFILESIZE
>         to set shell history size. Note that its max value is capped
>         by "History size" setting in library tuning section.
>
> +config FEATURE_SH_EMBEDDED_SCRIPTS
> +       bool "Embed scripts in the binary"
> +       default y
> +       depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH
> +       help
> +       Allow scripts to be compressed and embedded in the busybox
> +       binary. The scripts should be placed in the 'embed' directory
> +       at build time. Like applets, scripts can be run as
> +       'busybox SCRIPT ...' or by linking their name to the binary.
> +
> +       This also allows applets to be implemented as scripts: place
> +       the script in 'applets_sh' and a stub C file containing
> +       configuration in the appropriate subsystem directory.
> +
>  endif # Options common to all shells
>
>  endmenu
> diff --git a/shell/ash.c b/shell/ash.c
> index 04e4006c8..9ce1d1a76 100644
> --- a/shell/ash.c
> +++ b/shell/ash.c
> @@ -148,20 +148,6 @@
>  //config:      you to run the specified command or builtin,
>  //config:      even when there is a function with the same name.
>  //config:
> -//config:config ASH_EMBEDDED_SCRIPTS
> -//config:      bool "Embed scripts in the binary"
> -//config:      default y
> -//config:      depends on ASH || SH_IS_ASH || BASH_IS_ASH
> -//config:      help
> -//config:      Allow scripts to be compressed and embedded in the busybox
> -//config:      binary. The scripts should be placed in the 'embed' directory
> -//config:      at build time. Like applets, scripts can be run as
> -//config:      'busybox SCRIPT ...' or by linking their name to the binary.
> -//config:
> -//config:      This also allows applets to be implemented as scripts: place
> -//config:      the script in 'applets_sh' and a stub C file containing
> -//config:      configuration in the appropriate subsystem directory.
> -//config:
>  //config:endif # ash options
>
>  //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
> @@ -195,7 +181,7 @@
>  #include <sys/times.h>
>  #include <sys/utsname.h> /* for setting $HOSTNAME */
>  #include "busybox.h" /* for applet_names */
> -#if ENABLE_ASH_EMBEDDED_SCRIPTS
> +#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS
>  # include "embedded_scripts.h"
>  #else
>  # define NUM_SCRIPTS 0
> diff --git a/shell/hush.c b/shell/hush.c
> index 431010f09..90191408d 100644
> --- a/shell/hush.c
> +++ b/shell/hush.c
> @@ -367,6 +367,11 @@
>  # define PIPE_BUF 4096  /* amount of buffering in a pipe */
>  #endif
>
> +#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !(ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH)
> +# include "embedded_scripts.h"
> +#else
> +# define NUM_SCRIPTS 0
> +#endif
>
>  /* So far, all bash compat is controlled by one config option */
>  /* Separate defines document which part of code implements what */
> @@ -9951,6 +9956,14 @@ int hush_main(int argc, char **argv)
>         /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
>         flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0;
>         builtin_argc = 0;
> +#if NUM_SCRIPTS > 0
> +       if (argc < 0) {
> +               optarg = get_script_content(-argc - 1);
> +               optind = 0;
> +               argc = string_array_len(argv);
> +               goto run_script;
> +       }
> +#endif
>         while (1) {
>                 int opt = getopt(argc, argv, "+c:exinsl"
>  #if !BB_MMU
> @@ -9974,6 +9987,9 @@ int hush_main(int argc, char **argv)
>                          * Note: the form without ARG0 never happens:
>                          * sh ... -c 'builtin' BARGV... ""
>                          */
> +#if NUM_SCRIPTS > 0
> + run_script:
> +#endif
>                         if (!G.root_pid) {
>                                 G.root_pid = getpid();
>                                 G.root_ppid = getppid();
> diff --git a/util-linux/nologin.c b/util-linux/nologin.c
> index 0982fff3d..5e5e42305 100644
> --- a/util-linux/nologin.c
> +++ b/util-linux/nologin.c
> @@ -1,7 +1,7 @@
>  //config:config NOLOGIN
>  //config:      bool "nologin"
>  //config:      default y
> -//config:      depends on ASH_EMBEDDED_SCRIPTS
> +//config:      depends on FEATURE_SH_EMBEDDED_SCRIPTS
>  //config:      help
>  //config:      Politely refuse a login
>  //config:
> --
> 2.19.1
>
> _______________________________________________
> busybox mailing list
> busybox at busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox


More information about the busybox mailing list