From cda3fa8a257be0aa7023019609b32a0cf8ab2458 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Thu, 2 Sep 2021 14:10:45 +0800 Subject: [PATCH 01/24] [TACACS] Add plugin support to bash. --- src/bash/.gitignore | 4 + .../0001-Add-plugin-support-to-bash.patch | 246 +++++++++++ src/bash/plugin.c | 394 ++++++++++++++++++ src/bash/plugin.h | 75 ++++ src/bash/unittest/Makefile | 14 + src/bash/unittest/mock_helper.c | 218 ++++++++++ src/bash/unittest/mock_helper.h | 65 +++ src/bash/unittest/plugin_test.c | 216 ++++++++++ 8 files changed, 1232 insertions(+) create mode 100644 src/bash/0001-Add-plugin-support-to-bash.patch create mode 100644 src/bash/plugin.c create mode 100644 src/bash/plugin.h create mode 100644 src/bash/unittest/Makefile create mode 100644 src/bash/unittest/mock_helper.c create mode 100644 src/bash/unittest/mock_helper.h create mode 100644 src/bash/unittest/plugin_test.c diff --git a/src/bash/.gitignore b/src/bash/.gitignore index a0991ff4402b..7891e8b25cab 100644 --- a/src/bash/.gitignore +++ b/src/bash/.gitignore @@ -1,3 +1,7 @@ * !.gitignore !Makefile +!*.patch +!*.c +!*.h +!unittest/ diff --git a/src/bash/0001-Add-plugin-support-to-bash.patch b/src/bash/0001-Add-plugin-support-to-bash.patch new file mode 100644 index 000000000000..feba39c4fed8 --- /dev/null +++ b/src/bash/0001-Add-plugin-support-to-bash.patch @@ -0,0 +1,246 @@ +From 083b52469982fd000bf6beac3669e00cfc9bd250 Mon Sep 17 00:00:00 2001 +From: liuh-80 <58683130+liuh-80@users.noreply.github.com> +Date: Thu, 2 Sep 2021 14:00:52 +0800 +Subject: [PATCH] Add plugin support to bash. + +--- + Makefile.in | 10 ++++++---- + config.h.in | 3 +++ + configure | 13 +++++++++++++ + configure.ac | 6 ++++++ + execute_cmd.c | 13 +++++++++++++ + shell.c | 13 +++++++++++++ + 6 files changed, 54 insertions(+), 4 deletions(-) + +diff --git a/Makefile.in b/Makefile.in +index cf77228..e75dff7 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -430,7 +430,7 @@ CSOURCES = shell.c eval.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \ + input.c bashhist.c array.c arrayfunc.c assoc.c sig.c pathexp.c \ + unwind_prot.c siglist.c bashline.c bracecomp.c error.c \ + list.c stringlib.c locale.c findcmd.c redir.c \ +- pcomplete.c pcomplib.c syntax.c xmalloc.c ++ pcomplete.c pcomplib.c syntax.c xmalloc.c plugin.c + + HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ + general.h variables.h config.h $(ALLOC_HEADERS) alias.h \ +@@ -438,7 +438,7 @@ HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ + command.h input.h error.h bashansi.h dispose_cmd.h make_cmd.h \ + subst.h externs.h siglist.h bashhist.h bashline.h bashtypes.h \ + array.h arrayfunc.h sig.h mailcheck.h bashintl.h bashjmp.h \ +- execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h assoc.h \ ++ execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h assoc.h plugin.h \ + $(BASHINCFILES) + + SOURCES = $(CSOURCES) $(HSOURCES) $(BUILTIN_DEFS) +@@ -458,7 +458,7 @@ OBJECTS = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \ + trap.o input.o unwind_prot.o pathexp.o sig.o test.o version.o \ + alias.o array.o arrayfunc.o assoc.o braces.o bracecomp.o bashhist.o \ + bashline.o $(SIGLIST_O) list.o stringlib.o locale.o findcmd.o redir.o \ +- pcomplete.o pcomplib.o syntax.o xmalloc.o $(SIGNAMES_O) ++ pcomplete.o pcomplib.o syntax.o xmalloc.o plugin.o $(SIGNAMES_O) + + # Where the source code of the shell builtins resides. + BUILTIN_SRCDIR=$(srcdir)/builtins +@@ -929,7 +929,7 @@ eval.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h + eval.o: make_cmd.h subst.h sig.h pathnames.h externs.h + eval.o: input.h execute_cmd.h + execute_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h +-execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h ++execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h plugin.h + execute_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h + execute_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h + execute_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h +@@ -937,6 +937,8 @@ execute_cmd.o: ${BASHINCDIR}/memalloc.h ${GRAM_H} flags.h builtins.h jobs.h quit + execute_cmd.o: execute_cmd.h findcmd.h redir.h trap.h test.h pathexp.h + execute_cmd.o: $(DEFSRC)/common.h ${DEFDIR}/builtext.h ${GLOB_LIBSRC}/strmatch.h + execute_cmd.o: ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/chartypes.h ++execute_cmd.o: $(DEFSRC)/getopt.h ++plugin.o: plugin.h + expr.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h + expr.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h + expr.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h +diff --git a/config.h.in b/config.h.in +index 08af2ba..0ecbb8a 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -27,6 +27,9 @@ + BSD-like job control. */ + #undef JOB_CONTROL + ++/* Define BASH_PLUGIN if need plugin support. */ ++#undef BASH_PLUGIN ++ + /* Define ALIAS if you want the alias features. */ + #undef ALIAS + +diff --git a/configure b/configure +index 98bf890..a0fd9ac 100644 +--- a/configure ++++ b/configure +@@ -826,6 +826,7 @@ enable_single_help_strings + enable_strict_posix_default + enable_usg_echo_default + enable_xpg_echo_default ++enable_bash_plugin + enable_mem_scramble + enable_profiling + enable_static_link +@@ -1528,6 +1529,7 @@ Optional Features: + --enable-xpg-echo-default + make the echo builtin expand escape sequences by + default ++ --enable-bash-plugin enable bash plugin features + --enable-mem-scramble scramble memory on calls to malloc and free + --enable-profiling allow profiling with gprof + --enable-static-link link bash statically, for use as a root shell +@@ -3002,6 +3004,7 @@ opt_casemod_expansions=yes + opt_extglob_default=no + opt_dircomplete_expand_default=no + opt_globascii_default=no ++opt_bash_plugin=yes + + opt_static_link=no + opt_profiling=no +@@ -3023,6 +3026,7 @@ if test $opt_minimal_config = yes; then + opt_multibyte=yes opt_cond_regexp=no opt_coproc=no + opt_casemod_attrs=no opt_casemod_expansions=no opt_extglob_default=no + opt_globascii_default=no ++ opt_bash_plugin=no + fi + + # Check whether --enable-alias was given. +@@ -3200,6 +3204,11 @@ if test "${enable_xpg_echo_default+set}" = set; then : + enableval=$enable_xpg_echo_default; opt_xpg_echo=$enableval + fi + ++# Check whether --enable-bash-plugin was given. ++if test "${enable_bash_plugin+set}" = set; then : ++ enableval=$enable_bash_plugin; opt_bash_plugin=$enableval ++fi ++ + + # Check whether --enable-mem-scramble was given. + if test "${enable_mem_scramble+set}" = set; then : +@@ -3224,6 +3233,10 @@ fi + + + ++if test $opt_bash_plugin = yes; then ++$as_echo "#define BASH_PLUGIN 1" >>confdefs.h ++ ++fi + if test $opt_alias = yes; then + $as_echo "#define ALIAS 1" >>confdefs.h + +diff --git a/configure.ac b/configure.ac +index 97e8e04..6ba82b3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -193,6 +193,7 @@ opt_casemod_expansions=yes + opt_extglob_default=no + opt_dircomplete_expand_default=no + opt_globascii_default=no ++opt_bash_plugin=yes + + dnl options that affect how bash is compiled and linked + opt_static_link=no +@@ -214,6 +215,7 @@ if test $opt_minimal_config = yes; then + opt_multibyte=yes opt_cond_regexp=no opt_coproc=no + opt_casemod_attrs=no opt_casemod_expansions=no opt_extglob_default=no + opt_globascii_default=no ++ opt_bash_plugin=no + fi + + AC_ARG_ENABLE(alias, AC_HELP_STRING([--enable-alias], [enable shell aliases]), opt_alias=$enableval) +@@ -251,6 +253,7 @@ AC_ARG_ENABLE(single-help-strings, AC_HELP_STRING([--enable-single-help-strings] + AC_ARG_ENABLE(strict-posix-default, AC_HELP_STRING([--enable-strict-posix-default], [configure bash to be posix-conformant by default]), opt_strict_posix=$enableval) + AC_ARG_ENABLE(usg-echo-default, AC_HELP_STRING([--enable-usg-echo-default], [a synonym for --enable-xpg-echo-default]), opt_xpg_echo=$enableval) + AC_ARG_ENABLE(xpg-echo-default, AC_HELP_STRING([--enable-xpg-echo-default], [make the echo builtin expand escape sequences by default]), opt_xpg_echo=$enableval) ++AC_ARG_ENABLE(bash-plugin, AC_HELP_STRING([--enable-bash-plugin], [enable bash plugin features]), opt_bash_plugin=$enableval) + + dnl options that alter how bash is compiled and linked + AC_ARG_ENABLE(mem-scramble, AC_HELP_STRING([--enable-mem-scramble], [scramble memory on calls to malloc and free]), opt_memscramble=$enableval) +@@ -269,6 +272,9 @@ dnl opt_readline and opt_history are handled later, because AC_PROG_CC needs + dnl to be run before we can check the version of an already-installed readline + dnl library + ++if test $opt_bash_plugin = yes; then ++AC_DEFINE(BASH_PLUGIN) ++fi + if test $opt_alias = yes; then + AC_DEFINE(ALIAS) + fi +diff --git a/execute_cmd.c b/execute_cmd.c +index 9cebaef..894af08 100644 +--- a/execute_cmd.c ++++ b/execute_cmd.c +@@ -51,6 +51,10 @@ + # include + #endif + ++#if defined (BASH_PLUGIN) ++#include "plugin.h" ++#endif /* BASH_PLUGIN */ ++ + #include + + #if !defined (errno) +@@ -4998,6 +5002,15 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, + leave it there, in the same format that the user used to + type it in. */ + args = strvec_from_word_list (words, 0, 0, (int *)NULL); ++ ++ ++#if defined (BASH_PLUGIN) ++ result = invoke_plugin_on_shell_execve (current_user.user_name, command, args); ++ if (result) { ++ exit (EXECUTION_FAILURE); ++ } ++#endif /* BASH_PLUGIN */ ++ + exit (shell_execve (command, args, export_env)); + } + else +diff --git a/shell.c b/shell.c +index 2fd8179..299e757 100644 +--- a/shell.c ++++ b/shell.c +@@ -44,6 +44,10 @@ + # include + #endif + ++#if defined (BASH_PLUGIN) ++#include "plugin.h" ++#endif /* BASH_PLUGIN */ ++ + #include "bashintl.h" + + #define NEED_SH_SETLINEBUF_DECL /* used in externs.h */ +@@ -560,6 +564,10 @@ main (argc, argv, env) + if (shopt_alist) + run_shopt_alist (); + ++#if defined (BASH_PLUGIN) ++ load_plugins (); ++#endif /* BASH_PLUGIN */ ++ + /* From here on in, the shell must be a normal functioning shell. + Variables from the environment are expected to be set, etc. */ + shell_initialize (); +@@ -755,6 +763,11 @@ main (argc, argv, env) + /* Read commands until exit condition. */ + reader_loop (); + exit_shell (last_command_exit_value); ++ ++ ++#if defined (BASH_PLUGIN) ++ free_plugins (); ++#endif /* BASH_PLUGIN */ + } + + static int +-- +2.17.1.windows.2 + diff --git a/src/bash/plugin.c b/src/bash/plugin.c new file mode 100644 index 000000000000..528f8a42b36c --- /dev/null +++ b/src/bash/plugin.c @@ -0,0 +1,394 @@ +/* plugin.c -- Bash plugin support. */ + +/* Copyright (C) 1987-2016 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bash. If not, see . +*/ + +#include "config.h" + +#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX) + #pragma alloca +#endif /* _AIX && RISC6000 && !__GNUC__ */ + +// disable bash memory management when build for UT, PTR_T defined in xmalloc.h, define here for disable warning +#if defined (BASH_PLUGIN_UT) +# define _XMALLOC_H_ +# define PTR_T void * +# define malloc mock_malloc +# define free mock_free +#else +#endif + +#include +#include +#include "chartypes.h" +#include "bashtypes.h" +#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H) +# include +#endif +#include "filecntl.h" +#include "posixstat.h" +#include +#if defined (HAVE_SYS_PARAM_H) +# include +#endif + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include "posixtime.h" + +#if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE) +# include +#endif + +#if defined (HAVE_SYS_TIMES_H) && defined (HAVE_TIMES) +# include +#endif + +#include + +#if !defined (errno) +extern int errno; +#endif + +#define NEED_FPURGE_DECL +#define NEED_SH_SETLINEBUF_DECL + +#include "bashansi.h" +#include "bashintl.h" + +#include "shell.h" +#include /* use <...> so we pick it up from the build directory */ +#include "error.h" +#include "flags.h" +#include "builtins.h" +#include "hashlib.h" +#include "jobs.h" +#include "execute_cmd.h" +#include "findcmd.h" +#include "redir.h" +#include "trap.h" +#include "pathexp.h" +#include "hashcmd.h" + + +#if defined (BASH_PLUGIN) +#include "plugin.h" +#endif /* BASH_PLUGIN */ + +#if defined (COND_COMMAND) +# include "test.h" +#endif + +#include "builtins/common.h" + +#include "builtins/getopt.h" + +#include +#include + +#if defined (BUFFERED_INPUT) +# include "input.h" +#endif + +#if defined (ALIAS) +# include "alias.h" +#endif + +#if defined (HISTORY) +# include "bashhist.h" +#endif + +#if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR) +# include /* mbschr */ +#endif + +/* plugin configration file */ +const char *plugin_config_file = "/etc/bash_plugins.conf"; + +/* plugin on_shell_execve function name */ +static const char *on_shell_execve_function_name = "on_shell_execve"; + +/* plugin plugin_init function name */ +static const char *plugin_init_function_name = "plugin_init"; + +/* plugin plugin_uninit function name */ +static const char *plugin_uninit_function_name = "plugin_uninit"; + +/* plugin handle for test */ +PLUGIN_NODE *global_plugin_list = NULL; + +/* Load plugin by plugin path */ +void +append_plugin( + void *plugin_handle, + on_shell_execve_t *on_shell_execve, + plugin_init_t *plugin_init, + plugin_uninit_t *plugin_uninit) +{ + /* Create and initialize new plugin */ + PLUGIN_NODE *new_plugin_node = (PLUGIN_NODE*)malloc(sizeof(PLUGIN_NODE)); + new_plugin_node->next = NULL; + new_plugin_node->plugin_handle = plugin_handle; + new_plugin_node->on_shell_execve = on_shell_execve; + new_plugin_node->plugin_init = plugin_init; + new_plugin_node->plugin_uninit = plugin_uninit; + +#ifdef DEBUG + itrace("Plugin: append plugin node %p to global list %p\n", new_plugin_node, global_plugin_list); +#endif + + /* Find the pointer to the latest plugin node's 'next' field */ + PLUGIN_NODE **current_plugin_node = &global_plugin_list; + while (*current_plugin_node != NULL) { + current_plugin_node = &((*current_plugin_node)->next); + +#ifdef DEBUG + itrace("Plugin: founded next plugin node: %p\n", *current_plugin_node); +#endif + } + + /* append new plugin to tail node */ + *current_plugin_node = new_plugin_node; + +#ifdef DEBUG + itrace("Plugin: append new plugin node %p to %p\n", new_plugin_node, current_plugin_node); +#endif +} + + +/* Load plugin by plugin path */ +void +try_load_plugin_by_path(const char *plugin_path) +{ + /* Plugin handle */ + void *plugin_handle; + if ( (plugin_handle = dlopen(plugin_path, RTLD_LAZY)) == NULL) { +#ifdef DEBUG + itrace("Plugin: can't load plugin %s: %s\n", plugin_path, dlerror()); +#endif + return; + } + + /* Check if plugin support shell execve method */ + on_shell_execve_t* plugin_on_shell_execve_handle = dlsym(plugin_handle, on_shell_execve_function_name); + if (dlerror() != NULL) { + dlclose(plugin_handle); + +#ifdef DEBUG + itrace("Plugin: can't find on_shell_execve function %s: %s\n", plugin_path, dlerror()); +#endif + return; + } + + + /* Check if plugin support un-initialization method */ + plugin_uninit_t* plugin_uninit_handle = dlsym(plugin_handle, plugin_uninit_function_name); + if (dlerror() != NULL) { + dlclose(plugin_handle); + +#ifdef DEBUG + itrace("Plugin: can't find plugin_uninit function %s: %s\n", plugin_path, dlerror()); +#endif + return; + } + + /* Check if plugin support initialization method */ + plugin_init_t* plugin_init_handle = dlsym(plugin_handle, plugin_init_function_name); + if (dlerror() != NULL) { + dlclose(plugin_handle); + +#ifdef DEBUG + itrace("Plugin: can't find plugin_init function %s: %s\n", plugin_path, dlerror()); +#endif + return; + } + else { + /* Initialize plugin */ + plugin_init_handle(); + } + + /* Add plugin to plugin list */ + append_plugin(plugin_handle, + plugin_on_shell_execve_handle, + plugin_init_handle, + plugin_uninit_handle); + +#ifdef DEBUG + itrace("Plugin: plugin %s loaded\n", plugin_path); +#endif +} + +/* Load plugin by config file */ +void +load_plugin_by_config(const char *config_filename) +{ + FILE *config_file; + char buffer[256]; + + config_file = fopen(config_filename, "r"); + if(config_file == NULL) { +#ifdef DEBUG + itrace("Plugin: can't open plugin config file %s: %s\n", config_filename, strerror(errno)); +#endif + return; + } + + while(fgets(buffer, sizeof buffer, config_file)) { + if(*buffer == '#' || isspace(*buffer)) { + /* ignore comments or white space. */ + continue; + } + + /* read to first whitespace. */ + strtok(buffer, " \t\n\r\f"); + + if(!strncmp(buffer, "plugin=", 7)) { + /* read plugin path. */ + char* plugin_path = strtok(buffer+7, " \t\n\r\f"); +#ifdef DEBUG + itrace("Plugin: load plugin: %s\n", plugin_path); +#endif + try_load_plugin_by_path(plugin_path); + } +#ifdef DEBUG + else { + /* output debug message. */ + itrace("Plugin: unrecognized parameter: %s\n", buffer); + } +#endif + } + + fclose(config_file); +} + +/* Free loaded plugins */ +void +free_loaded_plugins() +{ + if (global_plugin_list == NULL) { + return; + } + +#ifdef DEBUG + itrace("Plugin: start free plugin from global list %p\n", global_plugin_list); +#endif + + /* Walk to last plugin */ + PLUGIN_NODE *next_plugin_node = global_plugin_list; + while (next_plugin_node != NULL) { + + /* Unload plugin */ + next_plugin_node->plugin_uninit(); + dlclose(next_plugin_node->plugin_handle); + + /* Continue with next pligin */ + PLUGIN_NODE* current_plugin_node_memory = next_plugin_node; + next_plugin_node = next_plugin_node->next; + +#ifdef DEBUG + itrace("Plugin: next plugin address %p\n", next_plugin_node); +#endif + + /* Free plugin node memory, this may also reset all allocated memory depends on c lib implementation */ + free(current_plugin_node_memory); + } + + /* Reset plugin list */ + global_plugin_list = NULL; +} + +/* Invoke loaded plugins */ +int +invoke_loaded_plugins (user, shell_level, cmd, argv) + char *user; + int shell_level; + char *cmd; + char **argv; +{ + if (global_plugin_list == NULL) { + return 0; + } + +#ifdef DEBUG + itrace("Plugin: start invoke plugin from global list %p\n", global_plugin_list); +#endif + + /* Walk to last plugin */ + PLUGIN_NODE *next_plugin_node = global_plugin_list; + while (next_plugin_node != NULL) { + + /* Call plugin method */ + int plugin_error_code = next_plugin_node->on_shell_execve(user, shell_level, cmd, argv); + if (plugin_error_code != 0) { +#ifdef DEBUG + itrace("Plugin: on_execve return error: %d\n", plugin_error_code); +#endif + /* Exit when plugin failed */ + return plugin_error_code; + } + + /* Continue with next pligin */ + next_plugin_node = next_plugin_node->next; + +#ifdef DEBUG + itrace("Plugin: next plugin address %p\n", next_plugin_node); +#endif + } + + return 0; +} + +/* Load all plugins。 */ +void +load_plugins () +{ + load_plugin_by_config(plugin_config_file); +} + +/* Free all plugins */ +void +free_plugins () +{ + free_loaded_plugins(); +} + +/* Invoke plugins before shell execve */ +int +invoke_plugin_on_shell_execve (user, cmd, argv) + char *user; + char *cmd; + char **argv; +{ + const char* shell_level_str = get_string_value ("SHLVL"); + const int shell_level = atoi (shell_level_str); + + if (absolute_program (cmd)) { + // find real path for relative path command + char resolved_path[PATH_MAX]; + + // real_path_buffer should not free here because we pass resolved_path as parameter. + char* real_path_buffer = realpath(cmd, resolved_path); + + return invoke_loaded_plugins(user, shell_level, resolved_path, argv); + } + else { + return invoke_loaded_plugins(user, shell_level, cmd, argv); + } +} diff --git a/src/bash/plugin.h b/src/bash/plugin.h new file mode 100644 index 000000000000..5aa5e67f53c1 --- /dev/null +++ b/src/bash/plugin.h @@ -0,0 +1,75 @@ +/* plugin.h - functions from plugin.c. */ + +/* Copyright (C) 1993-2015 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bash. If not, see . +*/ + +#if !defined (_PLUGIN_H_) +#define _PLUGIN_H_ + +#include "stdc.h" + +/* System-wide bash plugin configuration. */ +#define SYS_BASH_PLUGIN "/etc/bash.plugin" + +typedef enum { T_COMMAND } plugin_type_t; + +/* Bash plugin config. */ +typedef struct bash_plugin_conf +{ + const char *path; /* path to binary */ + char *name; /* Used to distinguish plugins */ +} bash_plugin_conf_t; + +/* plugin on_shell_execve function handle type */ +typedef int on_shell_execve_t (char *user, int shell_level, char *cmd, char **argv); + +/* plugin plugin_init function handle type */ +typedef int plugin_init_t (); + +/* plugin plugin_uninit function handle type */ +typedef int plugin_uninit_t (); + +/* Plugin list node. */ +typedef struct plugin_node { + + /* Next plugin pointer. */ + struct plugin_node *next; + + /* Plugin library handle. */ + void *plugin_handle; + + /* Plugin on_shell_execve function handle. */ + on_shell_execve_t *on_shell_execve; + + /* Plugin plugin_init function handle. */ + plugin_init_t *plugin_init; + + /* Plugin plugin_uninit function handle. */ + plugin_uninit_t *plugin_uninit; +} PLUGIN_NODE; + +/* Load all plugins */ +extern void load_plugins __P((void)); + +/* Free all plugins */ +extern void free_plugins __P((void)); + +/* Invoke plugins before shell execve */ +extern int invoke_plugin_on_shell_execve __P((char *, char *, char **)); + +#endif /* _PLUGIN_H_ */ diff --git a/src/bash/unittest/Makefile b/src/bash/unittest/Makefile new file mode 100644 index 000000000000..99f0b08a2eca --- /dev/null +++ b/src/bash/unittest/Makefile @@ -0,0 +1,14 @@ +#disable some warning because UT need test functions not in header file. +CFLAGS = -Wno-parentheses -Wno-format-security -Wno-implicit-function-declaration -c +IFLAGS = -I.. -I../include -I../lib +MFLAG = -DDEBUG -DBASH_PLUGIN_UT + +all: + gcc plugin_test.c $(IFLAGS) $(CFLAGS) -o plugin_test.o + gcc mock_helper.c $(IFLAGS) $(CFLAGS) -o mock_helper.o + gcc ../plugin.c $(IFLAGS) $(CFLAGS) $(MFLAG) -o plugin.o + gcc plugin_test.o mock_helper.o plugin.o -o plugin_test -lc -lcunit + +clean: + rm *.o + rm plugin_test diff --git a/src/bash/unittest/mock_helper.c b/src/bash/unittest/mock_helper.c new file mode 100644 index 000000000000..dfbf3a6444aa --- /dev/null +++ b/src/bash/unittest/mock_helper.c @@ -0,0 +1,218 @@ +/* mock_helper.c -- mock helper for bash plugin UT. */ +#include +#include +#include +#include +#include +#include +#include "mock_helper.h" + +// define BASH_PLUGIN_UT_DEBUG to output UT debug message. +//#define BASH_PLUGIN_UT_DEBUG +#if defined (BASH_PLUGIN_UT_DEBUG) +# define debug_printf printf +#else +# define debug_printf +#endif + +/* itrace buffer */ +char mock_itrace_message_buffer[1024]; + +/* bash run command buffer */ +char mock_onshell_execve_command_buffer[1024]; + +/* plugin handles. */ +void* mock_plugin_handle = (void*)TEST_MOCK_PLUGIN_HANDLE; +void* mock_plugin_default_function_handle = (void*)0x2234; +void* mock_plugin_on_shell_execve_handle = (void*)0x3234; +char* mock_dlerror_failed = "MOCK error"; +char* mock_dlerror = NULL; + +/* define test scenarios for mock functions return different value by scenario. */ +int test_scenario; + +/* define test scenarios for different return value. */ +int plugin_init_status; + +/* define memory allocate counter. */ +int memory_allocate_count; + +/* Set test scenario for test*/ +void set_test_scenario(int scenario) +{ + test_scenario = scenario; +} + +/* Get test scenario for test*/ +int get_test_scenario() +{ + return test_scenario; +} + +/* Set plugin init status for test*/ +void set_plugin_init_status(int status) +{ + plugin_init_status = status; +} + +/* Get plugin init status for test*/ +int get_plugin_init_status() +{ + return plugin_init_status; +} + +/* Set memory allocate count for test*/ +void set_memory_allocate_count(int count) +{ + memory_allocate_count = count; +} + +/* Get memory allocate count for test*/ +int get_memory_allocate_count() +{ + return memory_allocate_count; +} + +/* MOCK plugin_init method*/ +int mock_plugin_init() +{ + set_plugin_init_status(PLUGIN_INITIALIZED); +} + +/* MOCK plugin_init method*/ +int mock_plugin_uninit() +{ + set_plugin_init_status(PLUGIN_NOT_INITIALIZE); +} + +/* MOCK on_shell_execve method*/ +int mock_on_shell_execve (char *user, int shell_level, char *cmd, char **argv) +{ + // set mock command data to buffer for UT. + memset(mock_onshell_execve_command_buffer, 0, sizeof(mock_onshell_execve_command_buffer)); + + snprintf(mock_onshell_execve_command_buffer, sizeof(mock_onshell_execve_command_buffer), "on_shell_execve: user: %s, level: %d, command: %s, argv: %p\n", user, shell_level, cmd, argv); + + debug_printf("MOCK: mock_on_shell_execve: %s\n", mock_onshell_execve_command_buffer); +} + +/* MOCK dlopen*/ +void *dlopen(const char *filename, int flags) +{ + debug_printf("MOCK: dlopen: %s\n", filename); + if (TEST_SCEANRIO_PLUGIN_NOT_EXIT == test_scenario) + { + // return null when plugin not exist + mock_dlerror = mock_dlerror_failed; + return NULL; + } + + // all other case return mock handle + mock_dlerror = NULL; + return mock_plugin_handle; +} + +/* MOCK dlclose*/ +int dlclose(void *handle) +{ + debug_printf("MOCK: dlclose: %p\n", handle); + // check if the close handle match the opened handle + CU_ASSERT_EQUAL(handle, mock_plugin_handle); +} + +/* MOCK dlsym*/ +void *dlsym(void *restrict handle, const char *restrict symbol) +{ + debug_printf("MOCK: dlsym: %p, %s\n", handle, symbol); + mock_dlerror = NULL; + switch (test_scenario) + { + case TEST_SCEANRIO_PLUGIN_EXECVE_NOT_EXIT: + if (strcmp(symbol, "on_shell_execve") == 0) + { + mock_dlerror = mock_dlerror_failed; + return NULL; + } + + case TEST_SCEANRIO_PLUGIN_UNINIT_NOT_EXIT: + if (strcmp(symbol, "plugin_uninit") == 0) + { + mock_dlerror = mock_dlerror_failed; + return NULL; + } + + case TEST_SCEANRIO_PLUGIN_INIT_NOT_EXIT: + if (strcmp(symbol, "plugin_init") == 0) + { + mock_dlerror = mock_dlerror_failed; + return NULL; + } + + case TEST_SCEANRIO_PLUGIN_INIT_SUCCESS: + if (strcmp(symbol, "plugin_init") == 0) + { + // return mock method handle so plugin framework will call it to initialize + return mock_plugin_init; + } + else if (strcmp(symbol, "plugin_uninit") == 0) + { + // return mock method handle so plugin framework will call it to initialize + return mock_plugin_uninit; + } + else if (strcmp(symbol, "on_shell_execve") == 0) + { + // return mock method handle so plugin framework will call it to initialize + return mock_on_shell_execve; + } + } + + return mock_plugin_default_function_handle; +} + +/* MOCK dlerror*/ +char *dlerror(void) +{ + return mock_dlerror; +} + +/* MOCK get_string_value*/ +char *get_string_value(const char * str) +{ + return "1"; +} + +/* MOCK absolute_program*/ +int absolute_program (const char * str) +{ + return 0; +} + +/* MOCK itrace*/ +void itrace (const char * format, ...) +{ + // set mock message data to buffer for UT. + memset(mock_itrace_message_buffer, 0, sizeof(mock_itrace_message_buffer)); + + va_list args; + va_start(args, format); + // save message to buffer to UT check later + vsnprintf(mock_itrace_message_buffer, sizeof(mock_itrace_message_buffer), format, args); + va_end(args); + debug_printf("MOCK: itrace: %s\n", mock_itrace_message_buffer); +} + +/* MOCK malloc method*/ +void* mock_malloc (size_t size) +{ + memory_allocate_count++; + debug_printf("MOCK: malloc memory count: %d\n", memory_allocate_count); + return malloc(size); +} + +/* MOCK free method*/ +void mock_free (void* ptr) +{ + memory_allocate_count--; + debug_printf("MOCK: free memory count: %d\n", memory_allocate_count); + free(ptr); +} \ No newline at end of file diff --git a/src/bash/unittest/mock_helper.h b/src/bash/unittest/mock_helper.h new file mode 100644 index 000000000000..1fcfeb39be9b --- /dev/null +++ b/src/bash/unittest/mock_helper.h @@ -0,0 +1,65 @@ +/* plugin.h - functions from plugin.c. */ + +/* Copyright (C) 1993-2015 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bash. If not, see . +*/ + +#if !defined (_MOCK_HELPER_H_) +#define _MOCK_HELPER_H_ + +#include "plugin.h" + +#define TEST_MOCK_PLUGIN_HANDLE 0x1234 + +#define TEST_SCEANRIO_PLUGIN_NOT_EXIT 1 +#define TEST_SCEANRIO_PLUGIN_EXECVE_NOT_EXIT 2 +#define TEST_SCEANRIO_PLUGIN_UNINIT_NOT_EXIT 3 +#define TEST_SCEANRIO_PLUGIN_INIT_NOT_EXIT 4 +#define TEST_SCEANRIO_PLUGIN_INIT_SUCCESS 5 + +#define PLUGIN_NOT_INITIALIZE -1 +#define PLUGIN_INITIALIZED 1 + +/* The global plugin list */ +extern PLUGIN_NODE *global_plugin_list; + +/* itrace buffer */ +extern char mock_itrace_message_buffer[1024]; + +/* bash run command buffer */ +extern char mock_onshell_execve_command_buffer[1024]; + +/* Set test scenario for test*/ +void set_test_scenario(int scenario); + +/* Get test scenario for test*/ +int get_test_scenario(); + +/* Set plugin init status for test*/ +void set_plugin_init_status(int status); + +/* Get plugin init status for test*/ +int get_plugin_init_status(); + +/* Set memory allocate count for test*/ +void set_memory_allocate_count(int count); + +/* Get memory allocate count for test*/ +int get_memory_allocate_count(); + + +#endif /* _MOCK_HELPER_H_ */ \ No newline at end of file diff --git a/src/bash/unittest/plugin_test.c b/src/bash/unittest/plugin_test.c new file mode 100644 index 000000000000..2788e4d57d74 --- /dev/null +++ b/src/bash/unittest/plugin_test.c @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include "plugin.h" +#include "mock_helper.h" + +int clean_up() { + return 0; +} + +int start_up() { + return 0; +} + +/* Test plugin not exist scenario */ +void testcase_try_load_plugin_by_path_not_exist() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_NOT_EXIT); + + try_load_plugin_by_path("./testplugin.so"); + + CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't load plugin ./testplugin.so: MOCK error\n"); +} + +/* Test plugin exist but not support shell_execve scenario */ +void testcase_try_load_plugin_by_path_execve_not_exist() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_EXECVE_NOT_EXIT); + + try_load_plugin_by_path("./testplugin.so"); + + CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't find on_shell_execve function ./testplugin.so: MOCK error\n"); +} + +/* Test plugin exist but not support plugin_uninit scenario */ +void testcase_try_load_plugin_by_path_plugin_uninit_not_exist() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_UNINIT_NOT_EXIT); + + try_load_plugin_by_path("./testplugin.so"); + + CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't find plugin_uninit function ./testplugin.so: MOCK error\n"); +} + +/* Test plugin exist but not support plugin_init scenario */ +void testcase_try_load_plugin_by_path_plugin_init_not_exist() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_NOT_EXIT); + + try_load_plugin_by_path("./testplugin.so"); + + CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't find plugin_init function ./testplugin.so: MOCK error\n"); +} + +/* Test plugin exist but not support plugin_init scenario */ +void testcase_try_load_plugin_by_path_plugin_init_success() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_SUCCESS); + set_memory_allocate_count(0); + set_plugin_init_status(PLUGIN_NOT_INITIALIZE); + + try_load_plugin_by_path("./testplugin.so"); + + // check plugin init success + CU_ASSERT_EQUAL(get_plugin_init_status(), PLUGIN_INITIALIZED); + + // check API success + CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: plugin ./testplugin.so loaded\n"); + + // check global plugin list not empty and contains correct pluginglobal_plugin_list + CU_ASSERT_NOT_EQUAL(global_plugin_list, NULL); + CU_ASSERT_EQUAL(global_plugin_list->plugin_handle, TEST_MOCK_PLUGIN_HANDLE); + + // release all loaded plugins + free_loaded_plugins(); + + // check if memory fully released + CU_ASSERT_EQUAL(global_plugin_list, NULL); + CU_ASSERT_EQUAL(get_memory_allocate_count(), 0); +} + +/* Test free loaded plugins */ +void testcase_release_loaded_plugin() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_SUCCESS); + set_memory_allocate_count(0); + try_load_plugin_by_path("./testplugin.so"); + + // check memory allocated + CU_ASSERT_NOT_EQUAL(get_memory_allocate_count(), 0); + + // check plugin init success + CU_ASSERT_EQUAL(get_plugin_init_status(), PLUGIN_INITIALIZED); + + // release all loaded plugins + free_loaded_plugins(); + + // check if memory fully released + CU_ASSERT_EQUAL(global_plugin_list, NULL); + CU_ASSERT_EQUAL(get_memory_allocate_count(), 0); +} + +/* Test load plugin by config */ +void testcase_load_plugin_by_config() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_SUCCESS); + set_memory_allocate_count(0); + load_plugin_by_config("./bash_plugins.conf"); + + // check memory allocated + CU_ASSERT_NOT_EQUAL(get_memory_allocate_count(), 0); + + // check plugin init success + CU_ASSERT_EQUAL(get_plugin_init_status(), PLUGIN_INITIALIZED); + + // check target plugin in config file loaded + CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: plugin /usr/lib/bash-plugins/another_test_plugin.so loaded\n"); + + // check there are 2 plugins loaded + CU_ASSERT_EQUAL(get_memory_allocate_count(), 2); + + // release all loaded plugins + free_loaded_plugins(); + + // check if memory fully released + CU_ASSERT_EQUAL(global_plugin_list, NULL); + printf("Count %d\n", get_memory_allocate_count()); + CU_ASSERT_EQUAL(get_memory_allocate_count(), 0); +} + +/* Test invoke on_shell_execve plugin method */ +void testcase_invoke_plugin_on_shell_execve() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_SUCCESS); + set_memory_allocate_count(0); + load_plugin_by_config("./bash_plugins.conf"); + + // invoke plugin method + char** pargv = (char**)0x5234; + invoke_plugin_on_shell_execve("testuser", "testcommand", pargv); + printf(mock_onshell_execve_command_buffer); + CU_ASSERT_STRING_EQUAL(mock_onshell_execve_command_buffer, "on_shell_execve: user: testuser, level: 1, command: testcommand, argv: 0x5234\n"); + + // release all loaded plugins + free_loaded_plugins(); + + // check if memory fully released + CU_ASSERT_EQUAL(global_plugin_list, NULL); + printf("Count %d\n", get_memory_allocate_count()); + CU_ASSERT_EQUAL(get_memory_allocate_count(), 0); +} + +int main(void) { + if (CUE_SUCCESS != CU_initialize_registry()) { + return CU_get_error(); + } + + CU_pSuite ste = CU_add_suite("plugin_test", start_up, clean_up); + if (NULL == ste) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (CU_get_error() != CUE_SUCCESS) { + fprintf(stderr, "Error creating suite: (%d)%s\n", CU_get_error(), CU_get_error_msg()); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_not_exist()...\n", testcase_try_load_plugin_by_path_not_exist)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_execve_not_exist()...\n", testcase_try_load_plugin_by_path_execve_not_exist)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_plugin_uninit_not_exist()...\n", testcase_try_load_plugin_by_path_plugin_uninit_not_exist)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_plugin_init_not_exist()...\n", testcase_try_load_plugin_by_path_plugin_init_not_exist)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_plugin_init_success()...\n", testcase_try_load_plugin_by_path_plugin_init_success)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_release_loaded_plugin()...\n", testcase_release_loaded_plugin)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_load_plugin_by_config()...\n", testcase_load_plugin_by_config)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_invoke_plugin_on_shell_execve()...\n", testcase_invoke_plugin_on_shell_execve)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (CU_get_error() != CUE_SUCCESS) { + fprintf(stderr, "Error adding test: (%d)%s\n", CU_get_error(), CU_get_error_msg()); + } + + // run all test + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_ErrorCode run_errors = CU_basic_run_suite(ste); + if (run_errors != CUE_SUCCESS) { + fprintf(stderr, "Error running tests: (%d)%s\n", run_errors, CU_get_error_msg()); + } + + CU_basic_show_failures(CU_get_failure_list()); + CU_cleanup_registry(); + return CU_get_error(); +} \ No newline at end of file From cadfc8f0c15a06f7192ab0ced0b3585b0fccacdf Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 3 Sep 2021 06:12:15 +0000 Subject: [PATCH 02/24] Build bash from source code --- rules/bash.mk | 4 ++-- slave.mk | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/rules/bash.mk b/rules/bash.mk index 9c0d0c1e86d1..b1abed863cd9 100644 --- a/rules/bash.mk +++ b/rules/bash.mk @@ -6,9 +6,9 @@ # completed. # Bash major release-number corresponding to Debian-8 (Jessie) -BASH_VERSION_MAJOR = 4.3 +BASH_VERSION_MAJOR = 5.0 # Bash complete release-number. This image contains all 4.3 fixes up to patch '42'. -BASH_VERSION_FULL = $(BASH_VERSION_MAJOR)-14 +BASH_VERSION_FULL = $(BASH_VERSION_MAJOR)-4 export BASH_VERSION_MAJOR BASH_VERSION_FULL diff --git a/slave.mk b/slave.mk index 9e4bf532bfda..8c1a1699a06d 100644 --- a/slave.mk +++ b/slave.mk @@ -910,7 +910,8 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ $(PYTHON_SWSSCOMMON) \ $(PYTHON3_SWSSCOMMON) \ $(SONIC_UTILITIES_DATA) \ - $(SONIC_HOST_SERVICES_DATA)) \ + $(SONIC_HOST_SERVICES_DATA) \ + $(BASH)) \ $$(addprefix $(TARGET_PATH)/,$$($$*_DOCKERS)) \ $$(addprefix $(TARGET_PATH)/,$$(SONIC_PACKAGES_LOCAL)) \ $$(addprefix $(FILES_PATH)/,$$($$*_FILES)) \ From 79b5004418ee3f67443facda6b0687e96d94cdf2 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Fri, 3 Sep 2021 14:15:37 +0800 Subject: [PATCH 03/24] Change diff file to based on 5.0-4 version --- .../0001-Add-plugin-support-to-bash.patch | 110 +++++++----------- 1 file changed, 44 insertions(+), 66 deletions(-) diff --git a/src/bash/0001-Add-plugin-support-to-bash.patch b/src/bash/0001-Add-plugin-support-to-bash.patch index feba39c4fed8..7d9641ba6446 100644 --- a/src/bash/0001-Add-plugin-support-to-bash.patch +++ b/src/bash/0001-Add-plugin-support-to-bash.patch @@ -1,22 +1,22 @@ -From 083b52469982fd000bf6beac3669e00cfc9bd250 Mon Sep 17 00:00:00 2001 +From dd62400bb86039d64114c49cdc7f68c35e6c2bfa Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> -Date: Thu, 2 Sep 2021 14:00:52 +0800 +Date: Fri, 3 Sep 2021 14:05:36 +0800 Subject: [PATCH] Add plugin support to bash. --- - Makefile.in | 10 ++++++---- + Makefile.in | 9 +++++---- config.h.in | 3 +++ - configure | 13 +++++++++++++ - configure.ac | 6 ++++++ - execute_cmd.c | 13 +++++++++++++ + configure | 9 +++++++++ + configure.ac | 7 +++++++ + execute_cmd.c | 9 +++++++++ shell.c | 13 +++++++++++++ - 6 files changed, 54 insertions(+), 4 deletions(-) + 6 files changed, 46 insertions(+), 4 deletions(-) diff --git a/Makefile.in b/Makefile.in -index cf77228..e75dff7 100644 +index 5fcb44b..2a11f69 100644 --- a/Makefile.in +++ b/Makefile.in -@@ -430,7 +430,7 @@ CSOURCES = shell.c eval.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \ +@@ -440,7 +440,7 @@ CSOURCES = shell.c eval.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \ input.c bashhist.c array.c arrayfunc.c assoc.c sig.c pathexp.c \ unwind_prot.c siglist.c bashline.c bracecomp.c error.c \ list.c stringlib.c locale.c findcmd.c redir.c \ @@ -25,7 +25,7 @@ index cf77228..e75dff7 100644 HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ general.h variables.h config.h $(ALLOC_HEADERS) alias.h \ -@@ -438,7 +438,7 @@ HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ +@@ -448,7 +448,7 @@ HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ command.h input.h error.h bashansi.h dispose_cmd.h make_cmd.h \ subst.h externs.h siglist.h bashhist.h bashline.h bashtypes.h \ array.h arrayfunc.h sig.h mailcheck.h bashintl.h bashjmp.h \ @@ -34,7 +34,7 @@ index cf77228..e75dff7 100644 $(BASHINCFILES) SOURCES = $(CSOURCES) $(HSOURCES) $(BUILTIN_DEFS) -@@ -458,7 +458,7 @@ OBJECTS = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \ +@@ -481,7 +481,7 @@ OBJECTS = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \ trap.o input.o unwind_prot.o pathexp.o sig.o test.o version.o \ alias.o array.o arrayfunc.o assoc.o braces.o bracecomp.o bashhist.o \ bashline.o $(SIGLIST_O) list.o stringlib.o locale.o findcmd.o redir.o \ @@ -43,29 +43,28 @@ index cf77228..e75dff7 100644 # Where the source code of the shell builtins resides. BUILTIN_SRCDIR=$(srcdir)/builtins -@@ -929,7 +929,7 @@ eval.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h - eval.o: make_cmd.h subst.h sig.h pathnames.h externs.h +@@ -1015,7 +1015,7 @@ eval.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h + eval.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h eval.o: input.h execute_cmd.h execute_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h -execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h +execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h plugin.h execute_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h execute_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h - execute_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h -@@ -937,6 +937,8 @@ execute_cmd.o: ${BASHINCDIR}/memalloc.h ${GRAM_H} flags.h builtins.h jobs.h quit - execute_cmd.o: execute_cmd.h findcmd.h redir.h trap.h test.h pathexp.h + execute_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h +@@ -1024,6 +1024,7 @@ execute_cmd.o: execute_cmd.h findcmd.h redir.h trap.h test.h pathexp.h execute_cmd.o: $(DEFSRC)/common.h ${DEFDIR}/builtext.h ${GLOB_LIBSRC}/strmatch.h execute_cmd.o: ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/chartypes.h -+execute_cmd.o: $(DEFSRC)/getopt.h + execute_cmd.o: $(DEFSRC)/getopt.h +plugin.o: plugin.h expr.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h expr.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h expr.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h diff --git a/config.h.in b/config.h.in -index 08af2ba..0ecbb8a 100644 +index 8554aec..b2b57de 100644 --- a/config.h.in +++ b/config.h.in -@@ -27,6 +27,9 @@ +@@ -38,6 +38,9 @@ BSD-like job control. */ #undef JOB_CONTROL @@ -76,10 +75,10 @@ index 08af2ba..0ecbb8a 100644 #undef ALIAS diff --git a/configure b/configure -index 98bf890..a0fd9ac 100644 +index 2f62662..fb033d5 100644 --- a/configure +++ b/configure -@@ -826,6 +826,7 @@ enable_single_help_strings +@@ -827,6 +827,7 @@ enable_single_help_strings enable_strict_posix_default enable_usg_echo_default enable_xpg_echo_default @@ -87,7 +86,7 @@ index 98bf890..a0fd9ac 100644 enable_mem_scramble enable_profiling enable_static_link -@@ -1528,6 +1529,7 @@ Optional Features: +@@ -1535,6 +1536,7 @@ Optional Features: --enable-xpg-echo-default make the echo builtin expand escape sequences by default @@ -95,23 +94,23 @@ index 98bf890..a0fd9ac 100644 --enable-mem-scramble scramble memory on calls to malloc and free --enable-profiling allow profiling with gprof --enable-static-link link bash statically, for use as a root shell -@@ -3002,6 +3004,7 @@ opt_casemod_expansions=yes - opt_extglob_default=no - opt_dircomplete_expand_default=no - opt_globascii_default=no +@@ -2989,6 +2991,7 @@ opt_dircomplete_expand_default=no + opt_globascii_default=yes + opt_function_import=yes + opt_dev_fd_stat_broken=no +opt_bash_plugin=yes opt_static_link=no opt_profiling=no -@@ -3023,6 +3026,7 @@ if test $opt_minimal_config = yes; then +@@ -3010,6 +3013,7 @@ if test $opt_minimal_config = yes; then opt_multibyte=yes opt_cond_regexp=no opt_coproc=no opt_casemod_attrs=no opt_casemod_expansions=no opt_extglob_default=no - opt_globascii_default=no + opt_globascii_default=yes + opt_bash_plugin=no fi # Check whether --enable-alias was given. -@@ -3200,6 +3204,11 @@ if test "${enable_xpg_echo_default+set}" = set; then : +@@ -3197,6 +3201,11 @@ if test "${enable_xpg_echo_default+set}" = set; then : enableval=$enable_xpg_echo_default; opt_xpg_echo=$enableval fi @@ -123,38 +122,27 @@ index 98bf890..a0fd9ac 100644 # Check whether --enable-mem-scramble was given. if test "${enable_mem_scramble+set}" = set; then : -@@ -3224,6 +3233,10 @@ fi - - - -+if test $opt_bash_plugin = yes; then -+$as_echo "#define BASH_PLUGIN 1" >>confdefs.h -+ -+fi - if test $opt_alias = yes; then - $as_echo "#define ALIAS 1" >>confdefs.h - diff --git a/configure.ac b/configure.ac -index 97e8e04..6ba82b3 100644 +index 52b4cdb..2d73d90 100644 --- a/configure.ac +++ b/configure.ac -@@ -193,6 +193,7 @@ opt_casemod_expansions=yes - opt_extglob_default=no - opt_dircomplete_expand_default=no - opt_globascii_default=no +@@ -185,6 +185,7 @@ opt_dircomplete_expand_default=no + opt_globascii_default=yes + opt_function_import=yes + opt_dev_fd_stat_broken=no +opt_bash_plugin=yes dnl options that affect how bash is compiled and linked opt_static_link=no -@@ -214,6 +215,7 @@ if test $opt_minimal_config = yes; then +@@ -206,6 +207,7 @@ if test $opt_minimal_config = yes; then opt_multibyte=yes opt_cond_regexp=no opt_coproc=no opt_casemod_attrs=no opt_casemod_expansions=no opt_extglob_default=no - opt_globascii_default=no + opt_globascii_default=yes + opt_bash_plugin=no fi AC_ARG_ENABLE(alias, AC_HELP_STRING([--enable-alias], [enable shell aliases]), opt_alias=$enableval) -@@ -251,6 +253,7 @@ AC_ARG_ENABLE(single-help-strings, AC_HELP_STRING([--enable-single-help-strings] +@@ -245,6 +247,7 @@ AC_ARG_ENABLE(single-help-strings, AC_HELP_STRING([--enable-single-help-strings] AC_ARG_ENABLE(strict-posix-default, AC_HELP_STRING([--enable-strict-posix-default], [configure bash to be posix-conformant by default]), opt_strict_posix=$enableval) AC_ARG_ENABLE(usg-echo-default, AC_HELP_STRING([--enable-usg-echo-default], [a synonym for --enable-xpg-echo-default]), opt_xpg_echo=$enableval) AC_ARG_ENABLE(xpg-echo-default, AC_HELP_STRING([--enable-xpg-echo-default], [make the echo builtin expand escape sequences by default]), opt_xpg_echo=$enableval) @@ -162,10 +150,11 @@ index 97e8e04..6ba82b3 100644 dnl options that alter how bash is compiled and linked AC_ARG_ENABLE(mem-scramble, AC_HELP_STRING([--enable-mem-scramble], [scramble memory on calls to malloc and free]), opt_memscramble=$enableval) -@@ -269,6 +272,9 @@ dnl opt_readline and opt_history are handled later, because AC_PROG_CC needs +@@ -263,6 +266,10 @@ dnl opt_readline and opt_history are handled later, because AC_PROG_CC needs dnl to be run before we can check the version of an already-installed readline dnl library ++ +if test $opt_bash_plugin = yes; then +AC_DEFINE(BASH_PLUGIN) +fi @@ -173,21 +162,10 @@ index 97e8e04..6ba82b3 100644 AC_DEFINE(ALIAS) fi diff --git a/execute_cmd.c b/execute_cmd.c -index 9cebaef..894af08 100644 +index 8b3c83a..5477853 100644 --- a/execute_cmd.c +++ b/execute_cmd.c -@@ -51,6 +51,10 @@ - # include - #endif - -+#if defined (BASH_PLUGIN) -+#include "plugin.h" -+#endif /* BASH_PLUGIN */ -+ - #include - - #if !defined (errno) -@@ -4998,6 +5002,15 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, +@@ -5458,6 +5458,15 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, leave it there, in the same format that the user used to type it in. */ args = strvec_from_word_list (words, 0, 0, (int *)NULL); @@ -204,10 +182,10 @@ index 9cebaef..894af08 100644 } else diff --git a/shell.c b/shell.c -index 2fd8179..299e757 100644 +index a2b2a55..0ec6d95 100644 --- a/shell.c +++ b/shell.c -@@ -44,6 +44,10 @@ +@@ -46,6 +46,10 @@ # include #endif @@ -218,7 +196,7 @@ index 2fd8179..299e757 100644 #include "bashintl.h" #define NEED_SH_SETLINEBUF_DECL /* used in externs.h */ -@@ -560,6 +564,10 @@ main (argc, argv, env) +@@ -561,6 +565,10 @@ main (argc, argv, env) if (shopt_alist) run_shopt_alist (); @@ -229,7 +207,7 @@ index 2fd8179..299e757 100644 /* From here on in, the shell must be a normal functioning shell. Variables from the environment are expected to be set, etc. */ shell_initialize (); -@@ -755,6 +763,11 @@ main (argc, argv, env) +@@ -804,6 +812,11 @@ main (argc, argv, env) /* Read commands until exit condition. */ reader_loop (); exit_shell (last_command_exit_value); From bea3b2848d14710ca387eaf7f330ada484d979de Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Fri, 3 Sep 2021 14:44:31 +0800 Subject: [PATCH 04/24] Change make file to apply plugin support diff. --- src/bash/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bash/Makefile b/src/bash/Makefile index 6576ff92e74a..84699a876889 100644 --- a/src/bash/Makefile +++ b/src/bash/Makefile @@ -8,6 +8,9 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : rm -rf bash-$(BASH_VERSION_MAJOR) dget -u https://launchpad.net/debian/+archive/primary/+sourcefiles/bash/$(BASH_VERSION_FULL)/bash_$(BASH_VERSION_FULL).dsc + + # Apply plugin suport patch + git apply 0001-Add-plugin-support-to-bash.patch pushd bash-$(BASH_VERSION_MAJOR) DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) From 2a167f5c84fee6ed0cc098595a68ebb3fe06de59 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Fri, 3 Sep 2021 15:56:00 +0800 Subject: [PATCH 05/24] Fix whitespace issue. --- .../0001-Add-plugin-support-to-bash.patch | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/bash/0001-Add-plugin-support-to-bash.patch b/src/bash/0001-Add-plugin-support-to-bash.patch index 7d9641ba6446..80b9b86bfa64 100644 --- a/src/bash/0001-Add-plugin-support-to-bash.patch +++ b/src/bash/0001-Add-plugin-support-to-bash.patch @@ -1,4 +1,4 @@ -From dd62400bb86039d64114c49cdc7f68c35e6c2bfa Mon Sep 17 00:00:00 2001 +From b4962d09ab2d41a5e993bf3d8e4ebe32114999dc Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Fri, 3 Sep 2021 14:05:36 +0800 Subject: [PATCH] Add plugin support to bash. @@ -8,9 +8,9 @@ Subject: [PATCH] Add plugin support to bash. config.h.in | 3 +++ configure | 9 +++++++++ configure.ac | 7 +++++++ - execute_cmd.c | 9 +++++++++ - shell.c | 13 +++++++++++++ - 6 files changed, 46 insertions(+), 4 deletions(-) + execute_cmd.c | 8 ++++++++ + shell.c | 12 ++++++++++++ + 6 files changed, 44 insertions(+), 4 deletions(-) diff --git a/Makefile.in b/Makefile.in index 5fcb44b..2a11f69 100644 @@ -162,27 +162,26 @@ index 52b4cdb..2d73d90 100644 AC_DEFINE(ALIAS) fi diff --git a/execute_cmd.c b/execute_cmd.c -index 8b3c83a..5477853 100644 +index 8b3c83a..c83efea 100644 --- a/execute_cmd.c +++ b/execute_cmd.c -@@ -5458,6 +5458,15 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, +@@ -5458,6 +5458,14 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, leave it there, in the same format that the user used to type it in. */ args = strvec_from_word_list (words, 0, 0, (int *)NULL); -+ -+ ++ +#if defined (BASH_PLUGIN) + result = invoke_plugin_on_shell_execve (current_user.user_name, command, args); + if (result) { + exit (EXECUTION_FAILURE); + } +#endif /* BASH_PLUGIN */ -+ ++ exit (shell_execve (command, args, export_env)); } else diff --git a/shell.c b/shell.c -index a2b2a55..0ec6d95 100644 +index a2b2a55..fb94b22 100644 --- a/shell.c +++ b/shell.c @@ -46,6 +46,10 @@ @@ -207,11 +206,10 @@ index a2b2a55..0ec6d95 100644 /* From here on in, the shell must be a normal functioning shell. Variables from the environment are expected to be set, etc. */ shell_initialize (); -@@ -804,6 +812,11 @@ main (argc, argv, env) +@@ -804,6 +812,10 @@ main (argc, argv, env) /* Read commands until exit condition. */ reader_loop (); exit_shell (last_command_exit_value); -+ + +#if defined (BASH_PLUGIN) + free_plugins (); From 6b57fe2643aa4b83e53c6ee4826ba75edbcd5a48 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 3 Sep 2021 09:31:57 +0000 Subject: [PATCH 06/24] Improve build config --- sonic-slave-buster/Dockerfile.j2 | 4 ++++ src/bash/Makefile | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/sonic-slave-buster/Dockerfile.j2 b/sonic-slave-buster/Dockerfile.j2 index bbd68a31396e..1b3173373c10 100644 --- a/sonic-slave-buster/Dockerfile.j2 +++ b/sonic-slave-buster/Dockerfile.j2 @@ -258,6 +258,10 @@ RUN apt-get update && apt-get install -y \ iproute2 \ # For bash texi2html \ + sharutils \ + locales \ + time \ + man2html-base \ # For initramfs shellcheck \ bash-completion \ diff --git a/src/bash/Makefile b/src/bash/Makefile index 84699a876889..407249300e2d 100644 --- a/src/bash/Makefile +++ b/src/bash/Makefile @@ -8,12 +8,15 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : rm -rf bash-$(BASH_VERSION_MAJOR) dget -u https://launchpad.net/debian/+archive/primary/+sourcefiles/bash/$(BASH_VERSION_FULL)/bash_$(BASH_VERSION_FULL).dsc - - # Apply plugin suport patch - git apply 0001-Add-plugin-support-to-bash.patch + pushd bash-$(BASH_VERSION_MAJOR) + + # Apply plugin suport patch + patch -p1 < ../0001-Add-plugin-support-to-bash.patch DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + + popd mv $* $(DEST)/ From 6dc25648157f8b39c74ed4584dbebdddd8b71fd2 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 3 Sep 2021 09:37:00 +0000 Subject: [PATCH 07/24] Improve build config --- sonic-slave-bullseye/Dockerfile.j2 | 4 ++++ sonic-slave-jessie/Dockerfile.j2 | 4 ++++ sonic-slave-stretch/Dockerfile.j2 | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/sonic-slave-bullseye/Dockerfile.j2 b/sonic-slave-bullseye/Dockerfile.j2 index fac3bbe2b4aa..412aac07b1f9 100644 --- a/sonic-slave-bullseye/Dockerfile.j2 +++ b/sonic-slave-bullseye/Dockerfile.j2 @@ -250,6 +250,10 @@ RUN apt-get update && apt-get install -y \ iproute2 \ # For bash texi2html \ + sharutils \ + locales \ + time \ + man2html-base \ # For initramfs shellcheck \ bash-completion \ diff --git a/sonic-slave-jessie/Dockerfile.j2 b/sonic-slave-jessie/Dockerfile.j2 index db8f0a49650d..b9375e65c76e 100644 --- a/sonic-slave-jessie/Dockerfile.j2 +++ b/sonic-slave-jessie/Dockerfile.j2 @@ -231,6 +231,10 @@ RUN apt-get update && apt-get install -y \ texlive-latex-recommended \ # For bash texi2html \ + sharutils \ + locales \ + time \ + man2html-base \ # For initramfs bash-completion \ {% if CONFIGURED_ARCH == "amd64" -%} diff --git a/sonic-slave-stretch/Dockerfile.j2 b/sonic-slave-stretch/Dockerfile.j2 index cc45afbc6f82..0505d12af6e6 100644 --- a/sonic-slave-stretch/Dockerfile.j2 +++ b/sonic-slave-stretch/Dockerfile.j2 @@ -254,6 +254,10 @@ RUN apt-get update && apt-get install -y \ iproute2 \ # For bash texi2html \ + sharutils \ + locales \ + time \ + man2html-base \ # For initramfs bash-completion \ {%- if CONFIGURED_ARCH == "amd64" %} From 1904a405ff7a7cdbfdd40d24cfea55d05a39212e Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Fri, 3 Sep 2021 09:53:42 +0000 Subject: [PATCH 08/24] Improve build config --- src/bash/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bash/Makefile b/src/bash/Makefile index 407249300e2d..08ab5c8cbd08 100644 --- a/src/bash/Makefile +++ b/src/bash/Makefile @@ -14,6 +14,9 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : # Apply plugin suport patch patch -p1 < ../0001-Add-plugin-support-to-bash.patch + cp ../plugin.h ./plugin.h + cp ../plugin.c ./plugin.c + cp ../unittest ./unittest DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) From f1b55e8e264152bb638a7d1ebd6f547421636f8f Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Mon, 6 Sep 2021 13:57:27 +0800 Subject: [PATCH 09/24] Improve PR code --- .../0001-Add-plugin-support-to-bash.patch | 222 ---------- src/bash/Makefile | 5 +- src/bash/plugin.c | 394 ------------------ src/bash/plugin.h | 75 ---- src/bash/unittest/Makefile | 14 - src/bash/unittest/mock_helper.c | 218 ---------- src/bash/unittest/mock_helper.h | 65 --- src/bash/unittest/plugin_test.c | 216 ---------- 8 files changed, 4 insertions(+), 1205 deletions(-) delete mode 100644 src/bash/0001-Add-plugin-support-to-bash.patch delete mode 100644 src/bash/plugin.c delete mode 100644 src/bash/plugin.h delete mode 100644 src/bash/unittest/Makefile delete mode 100644 src/bash/unittest/mock_helper.c delete mode 100644 src/bash/unittest/mock_helper.h delete mode 100644 src/bash/unittest/plugin_test.c diff --git a/src/bash/0001-Add-plugin-support-to-bash.patch b/src/bash/0001-Add-plugin-support-to-bash.patch deleted file mode 100644 index 80b9b86bfa64..000000000000 --- a/src/bash/0001-Add-plugin-support-to-bash.patch +++ /dev/null @@ -1,222 +0,0 @@ -From b4962d09ab2d41a5e993bf3d8e4ebe32114999dc Mon Sep 17 00:00:00 2001 -From: liuh-80 <58683130+liuh-80@users.noreply.github.com> -Date: Fri, 3 Sep 2021 14:05:36 +0800 -Subject: [PATCH] Add plugin support to bash. - ---- - Makefile.in | 9 +++++---- - config.h.in | 3 +++ - configure | 9 +++++++++ - configure.ac | 7 +++++++ - execute_cmd.c | 8 ++++++++ - shell.c | 12 ++++++++++++ - 6 files changed, 44 insertions(+), 4 deletions(-) - -diff --git a/Makefile.in b/Makefile.in -index 5fcb44b..2a11f69 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -440,7 +440,7 @@ CSOURCES = shell.c eval.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \ - input.c bashhist.c array.c arrayfunc.c assoc.c sig.c pathexp.c \ - unwind_prot.c siglist.c bashline.c bracecomp.c error.c \ - list.c stringlib.c locale.c findcmd.c redir.c \ -- pcomplete.c pcomplib.c syntax.c xmalloc.c -+ pcomplete.c pcomplib.c syntax.c xmalloc.c plugin.c - - HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ - general.h variables.h config.h $(ALLOC_HEADERS) alias.h \ -@@ -448,7 +448,7 @@ HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ - command.h input.h error.h bashansi.h dispose_cmd.h make_cmd.h \ - subst.h externs.h siglist.h bashhist.h bashline.h bashtypes.h \ - array.h arrayfunc.h sig.h mailcheck.h bashintl.h bashjmp.h \ -- execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h assoc.h \ -+ execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h assoc.h plugin.h \ - $(BASHINCFILES) - - SOURCES = $(CSOURCES) $(HSOURCES) $(BUILTIN_DEFS) -@@ -481,7 +481,7 @@ OBJECTS = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \ - trap.o input.o unwind_prot.o pathexp.o sig.o test.o version.o \ - alias.o array.o arrayfunc.o assoc.o braces.o bracecomp.o bashhist.o \ - bashline.o $(SIGLIST_O) list.o stringlib.o locale.o findcmd.o redir.o \ -- pcomplete.o pcomplib.o syntax.o xmalloc.o $(SIGNAMES_O) -+ pcomplete.o pcomplib.o syntax.o xmalloc.o plugin.o $(SIGNAMES_O) - - # Where the source code of the shell builtins resides. - BUILTIN_SRCDIR=$(srcdir)/builtins -@@ -1015,7 +1015,7 @@ eval.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h - eval.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h - eval.o: input.h execute_cmd.h - execute_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h --execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h -+execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h plugin.h - execute_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h - execute_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h - execute_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h -@@ -1024,6 +1024,7 @@ execute_cmd.o: execute_cmd.h findcmd.h redir.h trap.h test.h pathexp.h - execute_cmd.o: $(DEFSRC)/common.h ${DEFDIR}/builtext.h ${GLOB_LIBSRC}/strmatch.h - execute_cmd.o: ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/chartypes.h - execute_cmd.o: $(DEFSRC)/getopt.h -+plugin.o: plugin.h - expr.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h - expr.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h - expr.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h -diff --git a/config.h.in b/config.h.in -index 8554aec..b2b57de 100644 ---- a/config.h.in -+++ b/config.h.in -@@ -38,6 +38,9 @@ - BSD-like job control. */ - #undef JOB_CONTROL - -+/* Define BASH_PLUGIN if need plugin support. */ -+#undef BASH_PLUGIN -+ - /* Define ALIAS if you want the alias features. */ - #undef ALIAS - -diff --git a/configure b/configure -index 2f62662..fb033d5 100644 ---- a/configure -+++ b/configure -@@ -827,6 +827,7 @@ enable_single_help_strings - enable_strict_posix_default - enable_usg_echo_default - enable_xpg_echo_default -+enable_bash_plugin - enable_mem_scramble - enable_profiling - enable_static_link -@@ -1535,6 +1536,7 @@ Optional Features: - --enable-xpg-echo-default - make the echo builtin expand escape sequences by - default -+ --enable-bash-plugin enable bash plugin features - --enable-mem-scramble scramble memory on calls to malloc and free - --enable-profiling allow profiling with gprof - --enable-static-link link bash statically, for use as a root shell -@@ -2989,6 +2991,7 @@ opt_dircomplete_expand_default=no - opt_globascii_default=yes - opt_function_import=yes - opt_dev_fd_stat_broken=no -+opt_bash_plugin=yes - - opt_static_link=no - opt_profiling=no -@@ -3010,6 +3013,7 @@ if test $opt_minimal_config = yes; then - opt_multibyte=yes opt_cond_regexp=no opt_coproc=no - opt_casemod_attrs=no opt_casemod_expansions=no opt_extglob_default=no - opt_globascii_default=yes -+ opt_bash_plugin=no - fi - - # Check whether --enable-alias was given. -@@ -3197,6 +3201,11 @@ if test "${enable_xpg_echo_default+set}" = set; then : - enableval=$enable_xpg_echo_default; opt_xpg_echo=$enableval - fi - -+# Check whether --enable-bash-plugin was given. -+if test "${enable_bash_plugin+set}" = set; then : -+ enableval=$enable_bash_plugin; opt_bash_plugin=$enableval -+fi -+ - - # Check whether --enable-mem-scramble was given. - if test "${enable_mem_scramble+set}" = set; then : -diff --git a/configure.ac b/configure.ac -index 52b4cdb..2d73d90 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -185,6 +185,7 @@ opt_dircomplete_expand_default=no - opt_globascii_default=yes - opt_function_import=yes - opt_dev_fd_stat_broken=no -+opt_bash_plugin=yes - - dnl options that affect how bash is compiled and linked - opt_static_link=no -@@ -206,6 +207,7 @@ if test $opt_minimal_config = yes; then - opt_multibyte=yes opt_cond_regexp=no opt_coproc=no - opt_casemod_attrs=no opt_casemod_expansions=no opt_extglob_default=no - opt_globascii_default=yes -+ opt_bash_plugin=no - fi - - AC_ARG_ENABLE(alias, AC_HELP_STRING([--enable-alias], [enable shell aliases]), opt_alias=$enableval) -@@ -245,6 +247,7 @@ AC_ARG_ENABLE(single-help-strings, AC_HELP_STRING([--enable-single-help-strings] - AC_ARG_ENABLE(strict-posix-default, AC_HELP_STRING([--enable-strict-posix-default], [configure bash to be posix-conformant by default]), opt_strict_posix=$enableval) - AC_ARG_ENABLE(usg-echo-default, AC_HELP_STRING([--enable-usg-echo-default], [a synonym for --enable-xpg-echo-default]), opt_xpg_echo=$enableval) - AC_ARG_ENABLE(xpg-echo-default, AC_HELP_STRING([--enable-xpg-echo-default], [make the echo builtin expand escape sequences by default]), opt_xpg_echo=$enableval) -+AC_ARG_ENABLE(bash-plugin, AC_HELP_STRING([--enable-bash-plugin], [enable bash plugin features]), opt_bash_plugin=$enableval) - - dnl options that alter how bash is compiled and linked - AC_ARG_ENABLE(mem-scramble, AC_HELP_STRING([--enable-mem-scramble], [scramble memory on calls to malloc and free]), opt_memscramble=$enableval) -@@ -263,6 +266,10 @@ dnl opt_readline and opt_history are handled later, because AC_PROG_CC needs - dnl to be run before we can check the version of an already-installed readline - dnl library - -+ -+if test $opt_bash_plugin = yes; then -+AC_DEFINE(BASH_PLUGIN) -+fi - if test $opt_alias = yes; then - AC_DEFINE(ALIAS) - fi -diff --git a/execute_cmd.c b/execute_cmd.c -index 8b3c83a..c83efea 100644 ---- a/execute_cmd.c -+++ b/execute_cmd.c -@@ -5458,6 +5458,14 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, - leave it there, in the same format that the user used to - type it in. */ - args = strvec_from_word_list (words, 0, 0, (int *)NULL); -+ -+#if defined (BASH_PLUGIN) -+ result = invoke_plugin_on_shell_execve (current_user.user_name, command, args); -+ if (result) { -+ exit (EXECUTION_FAILURE); -+ } -+#endif /* BASH_PLUGIN */ -+ - exit (shell_execve (command, args, export_env)); - } - else -diff --git a/shell.c b/shell.c -index a2b2a55..fb94b22 100644 ---- a/shell.c -+++ b/shell.c -@@ -46,6 +46,10 @@ - # include - #endif - -+#if defined (BASH_PLUGIN) -+#include "plugin.h" -+#endif /* BASH_PLUGIN */ -+ - #include "bashintl.h" - - #define NEED_SH_SETLINEBUF_DECL /* used in externs.h */ -@@ -561,6 +565,10 @@ main (argc, argv, env) - if (shopt_alist) - run_shopt_alist (); - -+#if defined (BASH_PLUGIN) -+ load_plugins (); -+#endif /* BASH_PLUGIN */ -+ - /* From here on in, the shell must be a normal functioning shell. - Variables from the environment are expected to be set, etc. */ - shell_initialize (); -@@ -804,6 +812,10 @@ main (argc, argv, env) - /* Read commands until exit condition. */ - reader_loop (); - exit_shell (last_command_exit_value); -+ -+#if defined (BASH_PLUGIN) -+ free_plugins (); -+#endif /* BASH_PLUGIN */ - } - - static int --- -2.17.1.windows.2 - diff --git a/src/bash/Makefile b/src/bash/Makefile index 407249300e2d..16acfa02f71d 100644 --- a/src/bash/Makefile +++ b/src/bash/Makefile @@ -13,7 +13,10 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : pushd bash-$(BASH_VERSION_MAJOR) # Apply plugin suport patch - patch -p1 < ../0001-Add-plugin-support-to-bash.patch + patch -p1 < ../patches/0001-Add-plugin-support-to-bash.patch + # copy UT and source code. + cp -a ../Files/. ./ + # build package DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) diff --git a/src/bash/plugin.c b/src/bash/plugin.c deleted file mode 100644 index 528f8a42b36c..000000000000 --- a/src/bash/plugin.c +++ /dev/null @@ -1,394 +0,0 @@ -/* plugin.c -- Bash plugin support. */ - -/* Copyright (C) 1987-2016 Free Software Foundation, Inc. - - This file is part of GNU Bash, the Bourne Again SHell. - - Bash is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Bash is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Bash. If not, see . -*/ - -#include "config.h" - -#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX) - #pragma alloca -#endif /* _AIX && RISC6000 && !__GNUC__ */ - -// disable bash memory management when build for UT, PTR_T defined in xmalloc.h, define here for disable warning -#if defined (BASH_PLUGIN_UT) -# define _XMALLOC_H_ -# define PTR_T void * -# define malloc mock_malloc -# define free mock_free -#else -#endif - -#include -#include -#include "chartypes.h" -#include "bashtypes.h" -#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H) -# include -#endif -#include "filecntl.h" -#include "posixstat.h" -#include -#if defined (HAVE_SYS_PARAM_H) -# include -#endif - -#if defined (HAVE_UNISTD_H) -# include -#endif - -#include "posixtime.h" - -#if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE) -# include -#endif - -#if defined (HAVE_SYS_TIMES_H) && defined (HAVE_TIMES) -# include -#endif - -#include - -#if !defined (errno) -extern int errno; -#endif - -#define NEED_FPURGE_DECL -#define NEED_SH_SETLINEBUF_DECL - -#include "bashansi.h" -#include "bashintl.h" - -#include "shell.h" -#include /* use <...> so we pick it up from the build directory */ -#include "error.h" -#include "flags.h" -#include "builtins.h" -#include "hashlib.h" -#include "jobs.h" -#include "execute_cmd.h" -#include "findcmd.h" -#include "redir.h" -#include "trap.h" -#include "pathexp.h" -#include "hashcmd.h" - - -#if defined (BASH_PLUGIN) -#include "plugin.h" -#endif /* BASH_PLUGIN */ - -#if defined (COND_COMMAND) -# include "test.h" -#endif - -#include "builtins/common.h" - -#include "builtins/getopt.h" - -#include -#include - -#if defined (BUFFERED_INPUT) -# include "input.h" -#endif - -#if defined (ALIAS) -# include "alias.h" -#endif - -#if defined (HISTORY) -# include "bashhist.h" -#endif - -#if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR) -# include /* mbschr */ -#endif - -/* plugin configration file */ -const char *plugin_config_file = "/etc/bash_plugins.conf"; - -/* plugin on_shell_execve function name */ -static const char *on_shell_execve_function_name = "on_shell_execve"; - -/* plugin plugin_init function name */ -static const char *plugin_init_function_name = "plugin_init"; - -/* plugin plugin_uninit function name */ -static const char *plugin_uninit_function_name = "plugin_uninit"; - -/* plugin handle for test */ -PLUGIN_NODE *global_plugin_list = NULL; - -/* Load plugin by plugin path */ -void -append_plugin( - void *plugin_handle, - on_shell_execve_t *on_shell_execve, - plugin_init_t *plugin_init, - plugin_uninit_t *plugin_uninit) -{ - /* Create and initialize new plugin */ - PLUGIN_NODE *new_plugin_node = (PLUGIN_NODE*)malloc(sizeof(PLUGIN_NODE)); - new_plugin_node->next = NULL; - new_plugin_node->plugin_handle = plugin_handle; - new_plugin_node->on_shell_execve = on_shell_execve; - new_plugin_node->plugin_init = plugin_init; - new_plugin_node->plugin_uninit = plugin_uninit; - -#ifdef DEBUG - itrace("Plugin: append plugin node %p to global list %p\n", new_plugin_node, global_plugin_list); -#endif - - /* Find the pointer to the latest plugin node's 'next' field */ - PLUGIN_NODE **current_plugin_node = &global_plugin_list; - while (*current_plugin_node != NULL) { - current_plugin_node = &((*current_plugin_node)->next); - -#ifdef DEBUG - itrace("Plugin: founded next plugin node: %p\n", *current_plugin_node); -#endif - } - - /* append new plugin to tail node */ - *current_plugin_node = new_plugin_node; - -#ifdef DEBUG - itrace("Plugin: append new plugin node %p to %p\n", new_plugin_node, current_plugin_node); -#endif -} - - -/* Load plugin by plugin path */ -void -try_load_plugin_by_path(const char *plugin_path) -{ - /* Plugin handle */ - void *plugin_handle; - if ( (plugin_handle = dlopen(plugin_path, RTLD_LAZY)) == NULL) { -#ifdef DEBUG - itrace("Plugin: can't load plugin %s: %s\n", plugin_path, dlerror()); -#endif - return; - } - - /* Check if plugin support shell execve method */ - on_shell_execve_t* plugin_on_shell_execve_handle = dlsym(plugin_handle, on_shell_execve_function_name); - if (dlerror() != NULL) { - dlclose(plugin_handle); - -#ifdef DEBUG - itrace("Plugin: can't find on_shell_execve function %s: %s\n", plugin_path, dlerror()); -#endif - return; - } - - - /* Check if plugin support un-initialization method */ - plugin_uninit_t* plugin_uninit_handle = dlsym(plugin_handle, plugin_uninit_function_name); - if (dlerror() != NULL) { - dlclose(plugin_handle); - -#ifdef DEBUG - itrace("Plugin: can't find plugin_uninit function %s: %s\n", plugin_path, dlerror()); -#endif - return; - } - - /* Check if plugin support initialization method */ - plugin_init_t* plugin_init_handle = dlsym(plugin_handle, plugin_init_function_name); - if (dlerror() != NULL) { - dlclose(plugin_handle); - -#ifdef DEBUG - itrace("Plugin: can't find plugin_init function %s: %s\n", plugin_path, dlerror()); -#endif - return; - } - else { - /* Initialize plugin */ - plugin_init_handle(); - } - - /* Add plugin to plugin list */ - append_plugin(plugin_handle, - plugin_on_shell_execve_handle, - plugin_init_handle, - plugin_uninit_handle); - -#ifdef DEBUG - itrace("Plugin: plugin %s loaded\n", plugin_path); -#endif -} - -/* Load plugin by config file */ -void -load_plugin_by_config(const char *config_filename) -{ - FILE *config_file; - char buffer[256]; - - config_file = fopen(config_filename, "r"); - if(config_file == NULL) { -#ifdef DEBUG - itrace("Plugin: can't open plugin config file %s: %s\n", config_filename, strerror(errno)); -#endif - return; - } - - while(fgets(buffer, sizeof buffer, config_file)) { - if(*buffer == '#' || isspace(*buffer)) { - /* ignore comments or white space. */ - continue; - } - - /* read to first whitespace. */ - strtok(buffer, " \t\n\r\f"); - - if(!strncmp(buffer, "plugin=", 7)) { - /* read plugin path. */ - char* plugin_path = strtok(buffer+7, " \t\n\r\f"); -#ifdef DEBUG - itrace("Plugin: load plugin: %s\n", plugin_path); -#endif - try_load_plugin_by_path(plugin_path); - } -#ifdef DEBUG - else { - /* output debug message. */ - itrace("Plugin: unrecognized parameter: %s\n", buffer); - } -#endif - } - - fclose(config_file); -} - -/* Free loaded plugins */ -void -free_loaded_plugins() -{ - if (global_plugin_list == NULL) { - return; - } - -#ifdef DEBUG - itrace("Plugin: start free plugin from global list %p\n", global_plugin_list); -#endif - - /* Walk to last plugin */ - PLUGIN_NODE *next_plugin_node = global_plugin_list; - while (next_plugin_node != NULL) { - - /* Unload plugin */ - next_plugin_node->plugin_uninit(); - dlclose(next_plugin_node->plugin_handle); - - /* Continue with next pligin */ - PLUGIN_NODE* current_plugin_node_memory = next_plugin_node; - next_plugin_node = next_plugin_node->next; - -#ifdef DEBUG - itrace("Plugin: next plugin address %p\n", next_plugin_node); -#endif - - /* Free plugin node memory, this may also reset all allocated memory depends on c lib implementation */ - free(current_plugin_node_memory); - } - - /* Reset plugin list */ - global_plugin_list = NULL; -} - -/* Invoke loaded plugins */ -int -invoke_loaded_plugins (user, shell_level, cmd, argv) - char *user; - int shell_level; - char *cmd; - char **argv; -{ - if (global_plugin_list == NULL) { - return 0; - } - -#ifdef DEBUG - itrace("Plugin: start invoke plugin from global list %p\n", global_plugin_list); -#endif - - /* Walk to last plugin */ - PLUGIN_NODE *next_plugin_node = global_plugin_list; - while (next_plugin_node != NULL) { - - /* Call plugin method */ - int plugin_error_code = next_plugin_node->on_shell_execve(user, shell_level, cmd, argv); - if (plugin_error_code != 0) { -#ifdef DEBUG - itrace("Plugin: on_execve return error: %d\n", plugin_error_code); -#endif - /* Exit when plugin failed */ - return plugin_error_code; - } - - /* Continue with next pligin */ - next_plugin_node = next_plugin_node->next; - -#ifdef DEBUG - itrace("Plugin: next plugin address %p\n", next_plugin_node); -#endif - } - - return 0; -} - -/* Load all plugins。 */ -void -load_plugins () -{ - load_plugin_by_config(plugin_config_file); -} - -/* Free all plugins */ -void -free_plugins () -{ - free_loaded_plugins(); -} - -/* Invoke plugins before shell execve */ -int -invoke_plugin_on_shell_execve (user, cmd, argv) - char *user; - char *cmd; - char **argv; -{ - const char* shell_level_str = get_string_value ("SHLVL"); - const int shell_level = atoi (shell_level_str); - - if (absolute_program (cmd)) { - // find real path for relative path command - char resolved_path[PATH_MAX]; - - // real_path_buffer should not free here because we pass resolved_path as parameter. - char* real_path_buffer = realpath(cmd, resolved_path); - - return invoke_loaded_plugins(user, shell_level, resolved_path, argv); - } - else { - return invoke_loaded_plugins(user, shell_level, cmd, argv); - } -} diff --git a/src/bash/plugin.h b/src/bash/plugin.h deleted file mode 100644 index 5aa5e67f53c1..000000000000 --- a/src/bash/plugin.h +++ /dev/null @@ -1,75 +0,0 @@ -/* plugin.h - functions from plugin.c. */ - -/* Copyright (C) 1993-2015 Free Software Foundation, Inc. - - This file is part of GNU Bash, the Bourne Again SHell. - - Bash is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Bash is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Bash. If not, see . -*/ - -#if !defined (_PLUGIN_H_) -#define _PLUGIN_H_ - -#include "stdc.h" - -/* System-wide bash plugin configuration. */ -#define SYS_BASH_PLUGIN "/etc/bash.plugin" - -typedef enum { T_COMMAND } plugin_type_t; - -/* Bash plugin config. */ -typedef struct bash_plugin_conf -{ - const char *path; /* path to binary */ - char *name; /* Used to distinguish plugins */ -} bash_plugin_conf_t; - -/* plugin on_shell_execve function handle type */ -typedef int on_shell_execve_t (char *user, int shell_level, char *cmd, char **argv); - -/* plugin plugin_init function handle type */ -typedef int plugin_init_t (); - -/* plugin plugin_uninit function handle type */ -typedef int plugin_uninit_t (); - -/* Plugin list node. */ -typedef struct plugin_node { - - /* Next plugin pointer. */ - struct plugin_node *next; - - /* Plugin library handle. */ - void *plugin_handle; - - /* Plugin on_shell_execve function handle. */ - on_shell_execve_t *on_shell_execve; - - /* Plugin plugin_init function handle. */ - plugin_init_t *plugin_init; - - /* Plugin plugin_uninit function handle. */ - plugin_uninit_t *plugin_uninit; -} PLUGIN_NODE; - -/* Load all plugins */ -extern void load_plugins __P((void)); - -/* Free all plugins */ -extern void free_plugins __P((void)); - -/* Invoke plugins before shell execve */ -extern int invoke_plugin_on_shell_execve __P((char *, char *, char **)); - -#endif /* _PLUGIN_H_ */ diff --git a/src/bash/unittest/Makefile b/src/bash/unittest/Makefile deleted file mode 100644 index 99f0b08a2eca..000000000000 --- a/src/bash/unittest/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -#disable some warning because UT need test functions not in header file. -CFLAGS = -Wno-parentheses -Wno-format-security -Wno-implicit-function-declaration -c -IFLAGS = -I.. -I../include -I../lib -MFLAG = -DDEBUG -DBASH_PLUGIN_UT - -all: - gcc plugin_test.c $(IFLAGS) $(CFLAGS) -o plugin_test.o - gcc mock_helper.c $(IFLAGS) $(CFLAGS) -o mock_helper.o - gcc ../plugin.c $(IFLAGS) $(CFLAGS) $(MFLAG) -o plugin.o - gcc plugin_test.o mock_helper.o plugin.o -o plugin_test -lc -lcunit - -clean: - rm *.o - rm plugin_test diff --git a/src/bash/unittest/mock_helper.c b/src/bash/unittest/mock_helper.c deleted file mode 100644 index dfbf3a6444aa..000000000000 --- a/src/bash/unittest/mock_helper.c +++ /dev/null @@ -1,218 +0,0 @@ -/* mock_helper.c -- mock helper for bash plugin UT. */ -#include -#include -#include -#include -#include -#include -#include "mock_helper.h" - -// define BASH_PLUGIN_UT_DEBUG to output UT debug message. -//#define BASH_PLUGIN_UT_DEBUG -#if defined (BASH_PLUGIN_UT_DEBUG) -# define debug_printf printf -#else -# define debug_printf -#endif - -/* itrace buffer */ -char mock_itrace_message_buffer[1024]; - -/* bash run command buffer */ -char mock_onshell_execve_command_buffer[1024]; - -/* plugin handles. */ -void* mock_plugin_handle = (void*)TEST_MOCK_PLUGIN_HANDLE; -void* mock_plugin_default_function_handle = (void*)0x2234; -void* mock_plugin_on_shell_execve_handle = (void*)0x3234; -char* mock_dlerror_failed = "MOCK error"; -char* mock_dlerror = NULL; - -/* define test scenarios for mock functions return different value by scenario. */ -int test_scenario; - -/* define test scenarios for different return value. */ -int plugin_init_status; - -/* define memory allocate counter. */ -int memory_allocate_count; - -/* Set test scenario for test*/ -void set_test_scenario(int scenario) -{ - test_scenario = scenario; -} - -/* Get test scenario for test*/ -int get_test_scenario() -{ - return test_scenario; -} - -/* Set plugin init status for test*/ -void set_plugin_init_status(int status) -{ - plugin_init_status = status; -} - -/* Get plugin init status for test*/ -int get_plugin_init_status() -{ - return plugin_init_status; -} - -/* Set memory allocate count for test*/ -void set_memory_allocate_count(int count) -{ - memory_allocate_count = count; -} - -/* Get memory allocate count for test*/ -int get_memory_allocate_count() -{ - return memory_allocate_count; -} - -/* MOCK plugin_init method*/ -int mock_plugin_init() -{ - set_plugin_init_status(PLUGIN_INITIALIZED); -} - -/* MOCK plugin_init method*/ -int mock_plugin_uninit() -{ - set_plugin_init_status(PLUGIN_NOT_INITIALIZE); -} - -/* MOCK on_shell_execve method*/ -int mock_on_shell_execve (char *user, int shell_level, char *cmd, char **argv) -{ - // set mock command data to buffer for UT. - memset(mock_onshell_execve_command_buffer, 0, sizeof(mock_onshell_execve_command_buffer)); - - snprintf(mock_onshell_execve_command_buffer, sizeof(mock_onshell_execve_command_buffer), "on_shell_execve: user: %s, level: %d, command: %s, argv: %p\n", user, shell_level, cmd, argv); - - debug_printf("MOCK: mock_on_shell_execve: %s\n", mock_onshell_execve_command_buffer); -} - -/* MOCK dlopen*/ -void *dlopen(const char *filename, int flags) -{ - debug_printf("MOCK: dlopen: %s\n", filename); - if (TEST_SCEANRIO_PLUGIN_NOT_EXIT == test_scenario) - { - // return null when plugin not exist - mock_dlerror = mock_dlerror_failed; - return NULL; - } - - // all other case return mock handle - mock_dlerror = NULL; - return mock_plugin_handle; -} - -/* MOCK dlclose*/ -int dlclose(void *handle) -{ - debug_printf("MOCK: dlclose: %p\n", handle); - // check if the close handle match the opened handle - CU_ASSERT_EQUAL(handle, mock_plugin_handle); -} - -/* MOCK dlsym*/ -void *dlsym(void *restrict handle, const char *restrict symbol) -{ - debug_printf("MOCK: dlsym: %p, %s\n", handle, symbol); - mock_dlerror = NULL; - switch (test_scenario) - { - case TEST_SCEANRIO_PLUGIN_EXECVE_NOT_EXIT: - if (strcmp(symbol, "on_shell_execve") == 0) - { - mock_dlerror = mock_dlerror_failed; - return NULL; - } - - case TEST_SCEANRIO_PLUGIN_UNINIT_NOT_EXIT: - if (strcmp(symbol, "plugin_uninit") == 0) - { - mock_dlerror = mock_dlerror_failed; - return NULL; - } - - case TEST_SCEANRIO_PLUGIN_INIT_NOT_EXIT: - if (strcmp(symbol, "plugin_init") == 0) - { - mock_dlerror = mock_dlerror_failed; - return NULL; - } - - case TEST_SCEANRIO_PLUGIN_INIT_SUCCESS: - if (strcmp(symbol, "plugin_init") == 0) - { - // return mock method handle so plugin framework will call it to initialize - return mock_plugin_init; - } - else if (strcmp(symbol, "plugin_uninit") == 0) - { - // return mock method handle so plugin framework will call it to initialize - return mock_plugin_uninit; - } - else if (strcmp(symbol, "on_shell_execve") == 0) - { - // return mock method handle so plugin framework will call it to initialize - return mock_on_shell_execve; - } - } - - return mock_plugin_default_function_handle; -} - -/* MOCK dlerror*/ -char *dlerror(void) -{ - return mock_dlerror; -} - -/* MOCK get_string_value*/ -char *get_string_value(const char * str) -{ - return "1"; -} - -/* MOCK absolute_program*/ -int absolute_program (const char * str) -{ - return 0; -} - -/* MOCK itrace*/ -void itrace (const char * format, ...) -{ - // set mock message data to buffer for UT. - memset(mock_itrace_message_buffer, 0, sizeof(mock_itrace_message_buffer)); - - va_list args; - va_start(args, format); - // save message to buffer to UT check later - vsnprintf(mock_itrace_message_buffer, sizeof(mock_itrace_message_buffer), format, args); - va_end(args); - debug_printf("MOCK: itrace: %s\n", mock_itrace_message_buffer); -} - -/* MOCK malloc method*/ -void* mock_malloc (size_t size) -{ - memory_allocate_count++; - debug_printf("MOCK: malloc memory count: %d\n", memory_allocate_count); - return malloc(size); -} - -/* MOCK free method*/ -void mock_free (void* ptr) -{ - memory_allocate_count--; - debug_printf("MOCK: free memory count: %d\n", memory_allocate_count); - free(ptr); -} \ No newline at end of file diff --git a/src/bash/unittest/mock_helper.h b/src/bash/unittest/mock_helper.h deleted file mode 100644 index 1fcfeb39be9b..000000000000 --- a/src/bash/unittest/mock_helper.h +++ /dev/null @@ -1,65 +0,0 @@ -/* plugin.h - functions from plugin.c. */ - -/* Copyright (C) 1993-2015 Free Software Foundation, Inc. - - This file is part of GNU Bash, the Bourne Again SHell. - - Bash is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Bash is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Bash. If not, see . -*/ - -#if !defined (_MOCK_HELPER_H_) -#define _MOCK_HELPER_H_ - -#include "plugin.h" - -#define TEST_MOCK_PLUGIN_HANDLE 0x1234 - -#define TEST_SCEANRIO_PLUGIN_NOT_EXIT 1 -#define TEST_SCEANRIO_PLUGIN_EXECVE_NOT_EXIT 2 -#define TEST_SCEANRIO_PLUGIN_UNINIT_NOT_EXIT 3 -#define TEST_SCEANRIO_PLUGIN_INIT_NOT_EXIT 4 -#define TEST_SCEANRIO_PLUGIN_INIT_SUCCESS 5 - -#define PLUGIN_NOT_INITIALIZE -1 -#define PLUGIN_INITIALIZED 1 - -/* The global plugin list */ -extern PLUGIN_NODE *global_plugin_list; - -/* itrace buffer */ -extern char mock_itrace_message_buffer[1024]; - -/* bash run command buffer */ -extern char mock_onshell_execve_command_buffer[1024]; - -/* Set test scenario for test*/ -void set_test_scenario(int scenario); - -/* Get test scenario for test*/ -int get_test_scenario(); - -/* Set plugin init status for test*/ -void set_plugin_init_status(int status); - -/* Get plugin init status for test*/ -int get_plugin_init_status(); - -/* Set memory allocate count for test*/ -void set_memory_allocate_count(int count); - -/* Get memory allocate count for test*/ -int get_memory_allocate_count(); - - -#endif /* _MOCK_HELPER_H_ */ \ No newline at end of file diff --git a/src/bash/unittest/plugin_test.c b/src/bash/unittest/plugin_test.c deleted file mode 100644 index 2788e4d57d74..000000000000 --- a/src/bash/unittest/plugin_test.c +++ /dev/null @@ -1,216 +0,0 @@ -#include -#include -#include -#include -#include "plugin.h" -#include "mock_helper.h" - -int clean_up() { - return 0; -} - -int start_up() { - return 0; -} - -/* Test plugin not exist scenario */ -void testcase_try_load_plugin_by_path_not_exist() { - set_test_scenario(TEST_SCEANRIO_PLUGIN_NOT_EXIT); - - try_load_plugin_by_path("./testplugin.so"); - - CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't load plugin ./testplugin.so: MOCK error\n"); -} - -/* Test plugin exist but not support shell_execve scenario */ -void testcase_try_load_plugin_by_path_execve_not_exist() { - set_test_scenario(TEST_SCEANRIO_PLUGIN_EXECVE_NOT_EXIT); - - try_load_plugin_by_path("./testplugin.so"); - - CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't find on_shell_execve function ./testplugin.so: MOCK error\n"); -} - -/* Test plugin exist but not support plugin_uninit scenario */ -void testcase_try_load_plugin_by_path_plugin_uninit_not_exist() { - set_test_scenario(TEST_SCEANRIO_PLUGIN_UNINIT_NOT_EXIT); - - try_load_plugin_by_path("./testplugin.so"); - - CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't find plugin_uninit function ./testplugin.so: MOCK error\n"); -} - -/* Test plugin exist but not support plugin_init scenario */ -void testcase_try_load_plugin_by_path_plugin_init_not_exist() { - set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_NOT_EXIT); - - try_load_plugin_by_path("./testplugin.so"); - - CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't find plugin_init function ./testplugin.so: MOCK error\n"); -} - -/* Test plugin exist but not support plugin_init scenario */ -void testcase_try_load_plugin_by_path_plugin_init_success() { - set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_SUCCESS); - set_memory_allocate_count(0); - set_plugin_init_status(PLUGIN_NOT_INITIALIZE); - - try_load_plugin_by_path("./testplugin.so"); - - // check plugin init success - CU_ASSERT_EQUAL(get_plugin_init_status(), PLUGIN_INITIALIZED); - - // check API success - CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: plugin ./testplugin.so loaded\n"); - - // check global plugin list not empty and contains correct pluginglobal_plugin_list - CU_ASSERT_NOT_EQUAL(global_plugin_list, NULL); - CU_ASSERT_EQUAL(global_plugin_list->plugin_handle, TEST_MOCK_PLUGIN_HANDLE); - - // release all loaded plugins - free_loaded_plugins(); - - // check if memory fully released - CU_ASSERT_EQUAL(global_plugin_list, NULL); - CU_ASSERT_EQUAL(get_memory_allocate_count(), 0); -} - -/* Test free loaded plugins */ -void testcase_release_loaded_plugin() { - set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_SUCCESS); - set_memory_allocate_count(0); - try_load_plugin_by_path("./testplugin.so"); - - // check memory allocated - CU_ASSERT_NOT_EQUAL(get_memory_allocate_count(), 0); - - // check plugin init success - CU_ASSERT_EQUAL(get_plugin_init_status(), PLUGIN_INITIALIZED); - - // release all loaded plugins - free_loaded_plugins(); - - // check if memory fully released - CU_ASSERT_EQUAL(global_plugin_list, NULL); - CU_ASSERT_EQUAL(get_memory_allocate_count(), 0); -} - -/* Test load plugin by config */ -void testcase_load_plugin_by_config() { - set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_SUCCESS); - set_memory_allocate_count(0); - load_plugin_by_config("./bash_plugins.conf"); - - // check memory allocated - CU_ASSERT_NOT_EQUAL(get_memory_allocate_count(), 0); - - // check plugin init success - CU_ASSERT_EQUAL(get_plugin_init_status(), PLUGIN_INITIALIZED); - - // check target plugin in config file loaded - CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: plugin /usr/lib/bash-plugins/another_test_plugin.so loaded\n"); - - // check there are 2 plugins loaded - CU_ASSERT_EQUAL(get_memory_allocate_count(), 2); - - // release all loaded plugins - free_loaded_plugins(); - - // check if memory fully released - CU_ASSERT_EQUAL(global_plugin_list, NULL); - printf("Count %d\n", get_memory_allocate_count()); - CU_ASSERT_EQUAL(get_memory_allocate_count(), 0); -} - -/* Test invoke on_shell_execve plugin method */ -void testcase_invoke_plugin_on_shell_execve() { - set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_SUCCESS); - set_memory_allocate_count(0); - load_plugin_by_config("./bash_plugins.conf"); - - // invoke plugin method - char** pargv = (char**)0x5234; - invoke_plugin_on_shell_execve("testuser", "testcommand", pargv); - printf(mock_onshell_execve_command_buffer); - CU_ASSERT_STRING_EQUAL(mock_onshell_execve_command_buffer, "on_shell_execve: user: testuser, level: 1, command: testcommand, argv: 0x5234\n"); - - // release all loaded plugins - free_loaded_plugins(); - - // check if memory fully released - CU_ASSERT_EQUAL(global_plugin_list, NULL); - printf("Count %d\n", get_memory_allocate_count()); - CU_ASSERT_EQUAL(get_memory_allocate_count(), 0); -} - -int main(void) { - if (CUE_SUCCESS != CU_initialize_registry()) { - return CU_get_error(); - } - - CU_pSuite ste = CU_add_suite("plugin_test", start_up, clean_up); - if (NULL == ste) { - CU_cleanup_registry(); - return CU_get_error(); - } - - if (CU_get_error() != CUE_SUCCESS) { - fprintf(stderr, "Error creating suite: (%d)%s\n", CU_get_error(), CU_get_error_msg()); - return CU_get_error(); - } - - if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_not_exist()...\n", testcase_try_load_plugin_by_path_not_exist)) { - CU_cleanup_registry(); - return CU_get_error(); - } - - if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_execve_not_exist()...\n", testcase_try_load_plugin_by_path_execve_not_exist)) { - CU_cleanup_registry(); - return CU_get_error(); - } - - if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_plugin_uninit_not_exist()...\n", testcase_try_load_plugin_by_path_plugin_uninit_not_exist)) { - CU_cleanup_registry(); - return CU_get_error(); - } - - if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_plugin_init_not_exist()...\n", testcase_try_load_plugin_by_path_plugin_init_not_exist)) { - CU_cleanup_registry(); - return CU_get_error(); - } - - if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_plugin_init_success()...\n", testcase_try_load_plugin_by_path_plugin_init_success)) { - CU_cleanup_registry(); - return CU_get_error(); - } - - if (!CU_add_test(ste, "Test testcase_release_loaded_plugin()...\n", testcase_release_loaded_plugin)) { - CU_cleanup_registry(); - return CU_get_error(); - } - - if (!CU_add_test(ste, "Test testcase_load_plugin_by_config()...\n", testcase_load_plugin_by_config)) { - CU_cleanup_registry(); - return CU_get_error(); - } - - if (!CU_add_test(ste, "Test testcase_invoke_plugin_on_shell_execve()...\n", testcase_invoke_plugin_on_shell_execve)) { - CU_cleanup_registry(); - return CU_get_error(); - } - - if (CU_get_error() != CUE_SUCCESS) { - fprintf(stderr, "Error adding test: (%d)%s\n", CU_get_error(), CU_get_error_msg()); - } - - // run all test - CU_basic_set_mode(CU_BRM_VERBOSE); - CU_ErrorCode run_errors = CU_basic_run_suite(ste); - if (run_errors != CUE_SUCCESS) { - fprintf(stderr, "Error running tests: (%d)%s\n", run_errors, CU_get_error_msg()); - } - - CU_basic_show_failures(CU_get_failure_list()); - CU_cleanup_registry(); - return CU_get_error(); -} \ No newline at end of file From da9d484757a434b0a7074ce863fb16304cfbd5be Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Mon, 6 Sep 2021 14:05:54 +0800 Subject: [PATCH 10/24] Add files. --- src/bash/.gitignore | 8 +- src/bash/Files/plugin.c | 394 ++++++++++++++++++ src/bash/Files/plugin.h | 75 ++++ src/bash/Files/unittest/Makefile | 14 + .../0001-Add-plugin-support-to-bash.patch | 278 ++++++++++++ 5 files changed, 765 insertions(+), 4 deletions(-) create mode 100644 src/bash/Files/plugin.c create mode 100644 src/bash/Files/plugin.h create mode 100644 src/bash/Files/unittest/Makefile create mode 100644 src/bash/patches/0001-Add-plugin-support-to-bash.patch diff --git a/src/bash/.gitignore b/src/bash/.gitignore index 7891e8b25cab..4d73f1b0d38e 100644 --- a/src/bash/.gitignore +++ b/src/bash/.gitignore @@ -1,7 +1,7 @@ * !.gitignore !Makefile -!*.patch -!*.c -!*.h -!unittest/ +!Files/ +!Files/* +!patches/ +!patches/* diff --git a/src/bash/Files/plugin.c b/src/bash/Files/plugin.c new file mode 100644 index 000000000000..2dd9aaaca873 --- /dev/null +++ b/src/bash/Files/plugin.c @@ -0,0 +1,394 @@ +/* plugin.c -- Bash plugin support. */ + +/* Copyright (C) 1987-2016 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bash. If not, see . +*/ + +#include "config.h" + +#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX) + #pragma alloca +#endif /* _AIX && RISC6000 && !__GNUC__ */ + +// disable bash memory management when build for UT, PTR_T defined in xmalloc.h, define here for disable warning +#if defined (BASH_PLUGIN_UT) +# define _XMALLOC_H_ +# define PTR_T void * +# define malloc mock_malloc +# define free mock_free +#else +#endif + +#include +#include +#include "chartypes.h" +#include "bashtypes.h" +#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H) +# include +#endif +#include "filecntl.h" +#include "posixstat.h" +#include +#if defined (HAVE_SYS_PARAM_H) +# include +#endif + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include "posixtime.h" + +#if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE) +# include +#endif + +#if defined (HAVE_SYS_TIMES_H) && defined (HAVE_TIMES) +# include +#endif + +#include + +#if !defined (errno) +extern int errno; +#endif + +#define NEED_FPURGE_DECL +#define NEED_SH_SETLINEBUF_DECL + +#include "bashansi.h" +#include "bashintl.h" + +#include "shell.h" +#include /* use <...> so we pick it up from the build directory */ +#include "error.h" +#include "flags.h" +#include "builtins.h" +#include "hashlib.h" +#include "jobs.h" +#include "execute_cmd.h" +#include "findcmd.h" +#include "redir.h" +#include "trap.h" +#include "pathexp.h" +#include "hashcmd.h" + + +#if defined (BASH_SHELL_EXECVE_PLUGIN) +#include "plugin.h" +#endif /* BASH_SHELL_EXECVE_PLUGIN */ + +#if defined (COND_COMMAND) +# include "test.h" +#endif + +#include "builtins/common.h" + +#include "builtins/getopt.h" + +#include +#include + +#if defined (BUFFERED_INPUT) +# include "input.h" +#endif + +#if defined (ALIAS) +# include "alias.h" +#endif + +#if defined (HISTORY) +# include "bashhist.h" +#endif + +#if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR) +# include /* mbschr */ +#endif + +/* plugin configration file */ +const char *plugin_config_file = "/etc/bash_plugins.conf"; + +/* plugin on_shell_execve function name */ +static const char *on_shell_execve_function_name = "on_shell_execve"; + +/* plugin plugin_init function name */ +static const char *plugin_init_function_name = "plugin_init"; + +/* plugin plugin_uninit function name */ +static const char *plugin_uninit_function_name = "plugin_uninit"; + +/* plugin handle for test */ +PLUGIN_NODE *global_plugin_list = NULL; + +/* Load plugin by plugin path */ +void +append_plugin( + void *plugin_handle, + on_shell_execve_t *on_shell_execve, + plugin_init_t *plugin_init, + plugin_uninit_t *plugin_uninit) +{ + /* Create and initialize new plugin */ + PLUGIN_NODE *new_plugin_node = (PLUGIN_NODE*)malloc(sizeof(PLUGIN_NODE)); + new_plugin_node->next = NULL; + new_plugin_node->plugin_handle = plugin_handle; + new_plugin_node->on_shell_execve = on_shell_execve; + new_plugin_node->plugin_init = plugin_init; + new_plugin_node->plugin_uninit = plugin_uninit; + +#ifdef DEBUG + itrace("Plugin: append plugin node %p to global list %p\n", new_plugin_node, global_plugin_list); +#endif + + /* Find the pointer to the latest plugin node's 'next' field */ + PLUGIN_NODE **current_plugin_node = &global_plugin_list; + while (*current_plugin_node != NULL) { + current_plugin_node = &((*current_plugin_node)->next); + +#ifdef DEBUG + itrace("Plugin: founded next plugin node: %p\n", *current_plugin_node); +#endif + } + + /* append new plugin to tail node */ + *current_plugin_node = new_plugin_node; + +#ifdef DEBUG + itrace("Plugin: append new plugin node %p to %p\n", new_plugin_node, current_plugin_node); +#endif +} + + +/* Load plugin by plugin path */ +void +try_load_plugin_by_path(const char *plugin_path) +{ + /* Plugin handle */ + void *plugin_handle; + if ( (plugin_handle = dlopen(plugin_path, RTLD_LAZY)) == NULL) { +#ifdef DEBUG + itrace("Plugin: can't load plugin %s: %s\n", plugin_path, dlerror()); +#endif + return; + } + + /* Check if plugin support shell execve method */ + on_shell_execve_t* plugin_on_shell_execve_handle = dlsym(plugin_handle, on_shell_execve_function_name); + if (dlerror() != NULL) { + dlclose(plugin_handle); + +#ifdef DEBUG + itrace("Plugin: can't find on_shell_execve function %s: %s\n", plugin_path, dlerror()); +#endif + return; + } + + + /* Check if plugin support un-initialization method */ + plugin_uninit_t* plugin_uninit_handle = dlsym(plugin_handle, plugin_uninit_function_name); + if (dlerror() != NULL) { + dlclose(plugin_handle); + +#ifdef DEBUG + itrace("Plugin: can't find plugin_uninit function %s: %s\n", plugin_path, dlerror()); +#endif + return; + } + + /* Check if plugin support initialization method */ + plugin_init_t* plugin_init_handle = dlsym(plugin_handle, plugin_init_function_name); + if (dlerror() != NULL) { + dlclose(plugin_handle); + +#ifdef DEBUG + itrace("Plugin: can't find plugin_init function %s: %s\n", plugin_path, dlerror()); +#endif + return; + } + else { + /* Initialize plugin */ + plugin_init_handle(); + } + + /* Add plugin to plugin list */ + append_plugin(plugin_handle, + plugin_on_shell_execve_handle, + plugin_init_handle, + plugin_uninit_handle); + +#ifdef DEBUG + itrace("Plugin: plugin %s loaded\n", plugin_path); +#endif +} + +/* Load plugin by config file */ +void +load_plugin_by_config(const char *config_filename) +{ + FILE *config_file; + char buffer[256]; + + config_file = fopen(config_filename, "r"); + if(config_file == NULL) { +#ifdef DEBUG + itrace("Plugin: can't open plugin config file %s: %s\n", config_filename, strerror(errno)); +#endif + return; + } + + while(fgets(buffer, sizeof buffer, config_file)) { + if(*buffer == '#' || isspace(*buffer)) { + /* ignore comments or white space. */ + continue; + } + + /* read to first whitespace. */ + strtok(buffer, " \t\n\r\f"); + + if(!strncmp(buffer, "plugin=", 7)) { + /* read plugin path. */ + char* plugin_path = strtok(buffer+7, " \t\n\r\f"); +#ifdef DEBUG + itrace("Plugin: load plugin: %s\n", plugin_path); +#endif + try_load_plugin_by_path(plugin_path); + } +#ifdef DEBUG + else { + /* output debug message. */ + itrace("Plugin: unrecognized parameter: %s\n", buffer); + } +#endif + } + + fclose(config_file); +} + +/* Free loaded plugins */ +void +free_loaded_plugins() +{ + if (global_plugin_list == NULL) { + return; + } + +#ifdef DEBUG + itrace("Plugin: start free plugin from global list %p\n", global_plugin_list); +#endif + + /* Walk to last plugin */ + PLUGIN_NODE *next_plugin_node = global_plugin_list; + while (next_plugin_node != NULL) { + + /* Unload plugin */ + next_plugin_node->plugin_uninit(); + dlclose(next_plugin_node->plugin_handle); + + /* Continue with next pligin */ + PLUGIN_NODE* current_plugin_node_memory = next_plugin_node; + next_plugin_node = next_plugin_node->next; + +#ifdef DEBUG + itrace("Plugin: next plugin address %p\n", next_plugin_node); +#endif + + /* Free plugin node memory, this may also reset all allocated memory depends on c lib implementation */ + free(current_plugin_node_memory); + } + + /* Reset plugin list */ + global_plugin_list = NULL; +} + +/* Invoke loaded plugins */ +int +invoke_loaded_plugins (user, shell_level, cmd, argv) + char *user; + int shell_level; + char *cmd; + char **argv; +{ + if (global_plugin_list == NULL) { + return 0; + } + +#ifdef DEBUG + itrace("Plugin: start invoke plugin from global list %p\n", global_plugin_list); +#endif + + /* Walk to last plugin */ + PLUGIN_NODE *next_plugin_node = global_plugin_list; + while (next_plugin_node != NULL) { + + /* Call plugin method */ + int plugin_error_code = next_plugin_node->on_shell_execve(user, shell_level, cmd, argv); + if (plugin_error_code != 0) { +#ifdef DEBUG + itrace("Plugin: on_execve return error: %d\n", plugin_error_code); +#endif + /* Exit when plugin failed */ + return plugin_error_code; + } + + /* Continue with next pligin */ + next_plugin_node = next_plugin_node->next; + +#ifdef DEBUG + itrace("Plugin: next plugin address %p\n", next_plugin_node); +#endif + } + + return 0; +} + +/* Load all plugins。 */ +void +load_plugins () +{ + load_plugin_by_config(plugin_config_file); +} + +/* Free all plugins */ +void +free_plugins () +{ + free_loaded_plugins(); +} + +/* Invoke plugins before shell execve */ +int +invoke_plugin_on_shell_execve (user, cmd, argv) + char *user; + char *cmd; + char **argv; +{ + const char* shell_level_str = get_string_value ("SHLVL"); + const int shell_level = atoi (shell_level_str); + + if (absolute_program (cmd)) { + // find real path for relative path command + char resolved_path[PATH_MAX]; + + // real_path_buffer should not free here because we pass resolved_path as parameter. + char* real_path_buffer = realpath(cmd, resolved_path); + + return invoke_loaded_plugins(user, shell_level, resolved_path, argv); + } + else { + return invoke_loaded_plugins(user, shell_level, cmd, argv); + } +} diff --git a/src/bash/Files/plugin.h b/src/bash/Files/plugin.h new file mode 100644 index 000000000000..5aa5e67f53c1 --- /dev/null +++ b/src/bash/Files/plugin.h @@ -0,0 +1,75 @@ +/* plugin.h - functions from plugin.c. */ + +/* Copyright (C) 1993-2015 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bash. If not, see . +*/ + +#if !defined (_PLUGIN_H_) +#define _PLUGIN_H_ + +#include "stdc.h" + +/* System-wide bash plugin configuration. */ +#define SYS_BASH_PLUGIN "/etc/bash.plugin" + +typedef enum { T_COMMAND } plugin_type_t; + +/* Bash plugin config. */ +typedef struct bash_plugin_conf +{ + const char *path; /* path to binary */ + char *name; /* Used to distinguish plugins */ +} bash_plugin_conf_t; + +/* plugin on_shell_execve function handle type */ +typedef int on_shell_execve_t (char *user, int shell_level, char *cmd, char **argv); + +/* plugin plugin_init function handle type */ +typedef int plugin_init_t (); + +/* plugin plugin_uninit function handle type */ +typedef int plugin_uninit_t (); + +/* Plugin list node. */ +typedef struct plugin_node { + + /* Next plugin pointer. */ + struct plugin_node *next; + + /* Plugin library handle. */ + void *plugin_handle; + + /* Plugin on_shell_execve function handle. */ + on_shell_execve_t *on_shell_execve; + + /* Plugin plugin_init function handle. */ + plugin_init_t *plugin_init; + + /* Plugin plugin_uninit function handle. */ + plugin_uninit_t *plugin_uninit; +} PLUGIN_NODE; + +/* Load all plugins */ +extern void load_plugins __P((void)); + +/* Free all plugins */ +extern void free_plugins __P((void)); + +/* Invoke plugins before shell execve */ +extern int invoke_plugin_on_shell_execve __P((char *, char *, char **)); + +#endif /* _PLUGIN_H_ */ diff --git a/src/bash/Files/unittest/Makefile b/src/bash/Files/unittest/Makefile new file mode 100644 index 000000000000..99f0b08a2eca --- /dev/null +++ b/src/bash/Files/unittest/Makefile @@ -0,0 +1,14 @@ +#disable some warning because UT need test functions not in header file. +CFLAGS = -Wno-parentheses -Wno-format-security -Wno-implicit-function-declaration -c +IFLAGS = -I.. -I../include -I../lib +MFLAG = -DDEBUG -DBASH_PLUGIN_UT + +all: + gcc plugin_test.c $(IFLAGS) $(CFLAGS) -o plugin_test.o + gcc mock_helper.c $(IFLAGS) $(CFLAGS) -o mock_helper.o + gcc ../plugin.c $(IFLAGS) $(CFLAGS) $(MFLAG) -o plugin.o + gcc plugin_test.o mock_helper.o plugin.o -o plugin_test -lc -lcunit + +clean: + rm *.o + rm plugin_test diff --git a/src/bash/patches/0001-Add-plugin-support-to-bash.patch b/src/bash/patches/0001-Add-plugin-support-to-bash.patch new file mode 100644 index 000000000000..5384120433c7 --- /dev/null +++ b/src/bash/patches/0001-Add-plugin-support-to-bash.patch @@ -0,0 +1,278 @@ +From bbb54228ffc084da4eea01e9227d4f0f96a1f814 Mon Sep 17 00:00:00 2001 +From: liuh-80 <58683130+liuh-80@users.noreply.github.com> +Date: Fri, 3 Sep 2021 14:05:36 +0800 +Subject: [PATCH] Add plugin support to bash. + +--- + Makefile.in | 14 +++++++++----- + config.h.in | 3 +++ + configure | 18 ++++++++++++++---- + configure.ac | 10 ++++++++++ + execute_cmd.c | 12 ++++++++++++ + shell.c | 12 ++++++++++++ + 6 files changed, 60 insertions(+), 9 deletions(-) + +diff --git a/Makefile.in b/Makefile.in +index 5fcb44b..9e4e4c3 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -379,6 +379,9 @@ LTLIBINTL = @LTLIBINTL@ + INTLLIBS = @INTLLIBS@ + INTLOBJS = @INTLOBJS@ + ++# Dynamic load library. ++DYNAMICLOAD_LIB = @DYNAMICLOAD_LIB@ ++ + # Our malloc. + MALLOC_TARGET = @MALLOC_TARGET@ + +@@ -420,7 +423,7 @@ BASHINCFILES = $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/ansi_stdlib.h \ + $(BASHINCDIR)/ocache.h + + LIBRARIES = $(GLOB_LIB) $(SHLIB_LIB) $(READLINE_LIB) $(HISTORY_LIB) $(TERMCAP_LIB) \ +- $(TILDE_LIB) $(MALLOC_LIB) $(INTL_LIB) $(LIBICONV) $(LOCAL_LIBS) ++ $(TILDE_LIB) $(MALLOC_LIB) $(INTL_LIB) $(LIBICONV) $(LOCAL_LIBS) $(DYNAMICLOAD_LIB) + + LIBDEP = $(GLOB_DEP) $(SHLIB_DEP) $(INTL_DEP) $(READLINE_DEP) $(HISTORY_DEP) $(TERMCAP_DEP) \ + $(TILDE_DEP) $(MALLOC_DEP) +@@ -440,7 +443,7 @@ CSOURCES = shell.c eval.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \ + input.c bashhist.c array.c arrayfunc.c assoc.c sig.c pathexp.c \ + unwind_prot.c siglist.c bashline.c bracecomp.c error.c \ + list.c stringlib.c locale.c findcmd.c redir.c \ +- pcomplete.c pcomplib.c syntax.c xmalloc.c ++ pcomplete.c pcomplib.c syntax.c xmalloc.c plugin.c + + HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ + general.h variables.h config.h $(ALLOC_HEADERS) alias.h \ +@@ -448,7 +451,7 @@ HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ + command.h input.h error.h bashansi.h dispose_cmd.h make_cmd.h \ + subst.h externs.h siglist.h bashhist.h bashline.h bashtypes.h \ + array.h arrayfunc.h sig.h mailcheck.h bashintl.h bashjmp.h \ +- execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h assoc.h \ ++ execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h assoc.h plugin.h \ + $(BASHINCFILES) + + SOURCES = $(CSOURCES) $(HSOURCES) $(BUILTIN_DEFS) +@@ -481,7 +484,7 @@ OBJECTS = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \ + trap.o input.o unwind_prot.o pathexp.o sig.o test.o version.o \ + alias.o array.o arrayfunc.o assoc.o braces.o bracecomp.o bashhist.o \ + bashline.o $(SIGLIST_O) list.o stringlib.o locale.o findcmd.o redir.o \ +- pcomplete.o pcomplib.o syntax.o xmalloc.o $(SIGNAMES_O) ++ pcomplete.o pcomplib.o syntax.o xmalloc.o plugin.o $(SIGNAMES_O) + + # Where the source code of the shell builtins resides. + BUILTIN_SRCDIR=$(srcdir)/builtins +@@ -1015,7 +1018,7 @@ eval.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h + eval.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h + eval.o: input.h execute_cmd.h + execute_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h +-execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h ++execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h plugin.h + execute_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h + execute_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h + execute_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h +@@ -1024,6 +1027,7 @@ execute_cmd.o: execute_cmd.h findcmd.h redir.h trap.h test.h pathexp.h + execute_cmd.o: $(DEFSRC)/common.h ${DEFDIR}/builtext.h ${GLOB_LIBSRC}/strmatch.h + execute_cmd.o: ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/chartypes.h + execute_cmd.o: $(DEFSRC)/getopt.h ++plugin.o: plugin.h + expr.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h + expr.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h + expr.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h +diff --git a/config.h.in b/config.h.in +index 8554aec..7f17024 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -38,6 +38,9 @@ + BSD-like job control. */ + #undef JOB_CONTROL + ++/* Define BASH_SHELL_EXECVE_PLUGIN if need plugin support. */ ++#undef BASH_SHELL_EXECVE_PLUGIN ++ + /* Define ALIAS if you want the alias features. */ + #undef ALIAS + +diff --git a/configure b/configure +index 2f62662..cae212f 100644 +--- a/configure ++++ b/configure +@@ -630,6 +630,7 @@ LOCAL_DEFS + LOCAL_LDFLAGS + LOCAL_CFLAGS + LOCAL_LIBS ++DYNAMICLOAD_LIB + MALLOC_DEBUG + DEBUG + RELSTATUS +@@ -827,6 +828,7 @@ enable_single_help_strings + enable_strict_posix_default + enable_usg_echo_default + enable_xpg_echo_default ++enable_bash_shell_execve_plugin + enable_mem_scramble + enable_profiling + enable_static_link +@@ -1535,6 +1537,7 @@ Optional Features: + --enable-xpg-echo-default + make the echo builtin expand escape sequences by + default ++ --enable-bash-plugin enable bash plugin features + --enable-mem-scramble scramble memory on calls to malloc and free + --enable-profiling allow profiling with gprof + --enable-static-link link bash statically, for use as a root shell +@@ -2989,6 +2992,7 @@ opt_dircomplete_expand_default=no + opt_globascii_default=yes + opt_function_import=yes + opt_dev_fd_stat_broken=no ++opt_bash_shell_execve_plugin=yes + + opt_static_link=no + opt_profiling=no +@@ -3010,6 +3014,7 @@ if test $opt_minimal_config = yes; then + opt_multibyte=yes opt_cond_regexp=no opt_coproc=no + opt_casemod_attrs=no opt_casemod_expansions=no opt_extglob_default=no + opt_globascii_default=yes ++ opt_bash_shell_execve_plugin=no + fi + + # Check whether --enable-alias was given. +@@ -3197,6 +3202,10 @@ if test "${enable_xpg_echo_default+set}" = set; then : + enableval=$enable_xpg_echo_default; opt_xpg_echo=$enableval + fi + ++# Check whether --enable-bash-shell-execve-plugin was given. ++if test "${enable_bash_shell_execve_plugin+set}" = set; then : ++ enableval=$enable_bash_shell_execve_plugin; opt_bash_shell_execve_plugin=$enableval ++fi + + # Check whether --enable-mem-scramble was given. + if test "${enable_mem_scramble+set}" = set; then : +@@ -3216,10 +3225,11 @@ fi + + + +- +- +- +- ++DYNAMICLOAD_LIB= ++if test $opt_bash_shell_execve_plugin = yes; then ++$as_echo "#define BASH_SHELL_EXECVE_PLUGIN 1" >>confdefs.h ++DYNAMICLOAD_LIB=-ldl ++fi + + if test $opt_alias = yes; then + $as_echo "#define ALIAS 1" >>confdefs.h +diff --git a/configure.ac b/configure.ac +index 52b4cdb..8070b94 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -185,6 +185,7 @@ opt_dircomplete_expand_default=no + opt_globascii_default=yes + opt_function_import=yes + opt_dev_fd_stat_broken=no ++opt_bash_shell_execve_plugin=yes + + dnl options that affect how bash is compiled and linked + opt_static_link=no +@@ -206,6 +207,7 @@ if test $opt_minimal_config = yes; then + opt_multibyte=yes opt_cond_regexp=no opt_coproc=no + opt_casemod_attrs=no opt_casemod_expansions=no opt_extglob_default=no + opt_globascii_default=yes ++ opt_bash_shell_execve_plugin=no + fi + + AC_ARG_ENABLE(alias, AC_HELP_STRING([--enable-alias], [enable shell aliases]), opt_alias=$enableval) +@@ -245,6 +247,7 @@ AC_ARG_ENABLE(single-help-strings, AC_HELP_STRING([--enable-single-help-strings] + AC_ARG_ENABLE(strict-posix-default, AC_HELP_STRING([--enable-strict-posix-default], [configure bash to be posix-conformant by default]), opt_strict_posix=$enableval) + AC_ARG_ENABLE(usg-echo-default, AC_HELP_STRING([--enable-usg-echo-default], [a synonym for --enable-xpg-echo-default]), opt_xpg_echo=$enableval) + AC_ARG_ENABLE(xpg-echo-default, AC_HELP_STRING([--enable-xpg-echo-default], [make the echo builtin expand escape sequences by default]), opt_xpg_echo=$enableval) ++AC_ARG_ENABLE(bash-shell-execve-plugin, AC_HELP_STRING([--enable-bash-shell-execve-plugin], [enable bash shell execve plugin features]), opt_bash_shell_execve_plugin=$enableval) + + dnl options that alter how bash is compiled and linked + AC_ARG_ENABLE(mem-scramble, AC_HELP_STRING([--enable-mem-scramble], [scramble memory on calls to malloc and free]), opt_memscramble=$enableval) +@@ -263,6 +266,13 @@ dnl opt_readline and opt_history are handled later, because AC_PROG_CC needs + dnl to be run before we can check the version of an already-installed readline + dnl library + ++DYNAMICLOAD_LIB= ++if test $opt_bash_shell_execve_plugin = yes; then ++AC_DEFINE(BASH_SHELL_EXECVE_PLUGIN) ++DYNAMICLOAD_LIB=-ldl ++fi ++AC_SUBST(DYNAMICLOAD_LIB) ++ + if test $opt_alias = yes; then + AC_DEFINE(ALIAS) + fi +diff --git a/execute_cmd.c b/execute_cmd.c +index 8b3c83a..b7157aa 100644 +--- a/execute_cmd.c ++++ b/execute_cmd.c +@@ -82,6 +82,10 @@ extern int errno; + # include "test.h" + #endif + ++#if defined (BASH_SHELL_EXECVE_PLUGIN) ++#include "plugin.h" ++#endif /* BASH_SHELL_EXECVE_PLUGIN */ ++ + #include "builtins/common.h" + #include "builtins/builtext.h" /* list of builtins */ + +@@ -5458,6 +5462,14 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, + leave it there, in the same format that the user used to + type it in. */ + args = strvec_from_word_list (words, 0, 0, (int *)NULL); ++ ++#if defined (BASH_SHELL_EXECVE_PLUGIN) ++ result = invoke_plugin_on_shell_execve (current_user.user_name, command, args); ++ if (result) { ++ exit (EXECUTION_FAILURE); ++ } ++#endif /* BASH_SHELL_EXECVE_PLUGIN */ ++ + exit (shell_execve (command, args, export_env)); + } + else +diff --git a/shell.c b/shell.c +index a2b2a55..237afbb 100644 +--- a/shell.c ++++ b/shell.c +@@ -46,6 +46,10 @@ + # include + #endif + ++#if defined (BASH_SHELL_EXECVE_PLUGIN) ++#include "plugin.h" ++#endif /* BASH_SHELL_EXECVE_PLUGIN */ ++ + #include "bashintl.h" + + #define NEED_SH_SETLINEBUF_DECL /* used in externs.h */ +@@ -561,6 +565,10 @@ main (argc, argv, env) + if (shopt_alist) + run_shopt_alist (); + ++#if defined (BASH_SHELL_EXECVE_PLUGIN) ++ load_plugins (); ++#endif /* BASH_SHELL_EXECVE_PLUGIN */ ++ + /* From here on in, the shell must be a normal functioning shell. + Variables from the environment are expected to be set, etc. */ + shell_initialize (); +@@ -804,6 +812,10 @@ main (argc, argv, env) + /* Read commands until exit condition. */ + reader_loop (); + exit_shell (last_command_exit_value); ++ ++#if defined (BASH_SHELL_EXECVE_PLUGIN) ++ free_plugins (); ++#endif /* BASH_SHELL_EXECVE_PLUGIN */ + } + + static int +-- +2.17.1.windows.2 + From c6cef30f0aa671edf28b740274f2c99e0bc5e4c1 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Mon, 6 Sep 2021 15:07:01 +0800 Subject: [PATCH 11/24] Improve PR. --- rules/bash.mk | 10 +- src/bash/Files/plugin.c | 394 ------------- src/bash/Files/plugin.h | 75 --- .../0001-Add-plugin-support-to-bash.patch | 541 +++++++++++++++++- 4 files changed, 532 insertions(+), 488 deletions(-) delete mode 100644 src/bash/Files/plugin.c delete mode 100644 src/bash/Files/plugin.h diff --git a/rules/bash.mk b/rules/bash.mk index b1abed863cd9..f881af664507 100644 --- a/rules/bash.mk +++ b/rules/bash.mk @@ -1,13 +1,11 @@ # bash package # -# Created to patch memory-leak issue in the bash-package included in Debian-8 (Jessie) -# release. This rule file, and the associated building-infra created to solve this -# bug (src/bash/), should be eliminated once the migration to Debian-9 (Stretch) is -# completed. +# Created to patch plugin support in the bash-package included in Debian-10 (Buster) +# release. -# Bash major release-number corresponding to Debian-8 (Jessie) +# Bash major release-number corresponding to Debian-10 (Buster) BASH_VERSION_MAJOR = 5.0 -# Bash complete release-number. This image contains all 4.3 fixes up to patch '42'. +# Bash complete release-number. This image contains all 5.0 fixes up to patch '4'. BASH_VERSION_FULL = $(BASH_VERSION_MAJOR)-4 export BASH_VERSION_MAJOR BASH_VERSION_FULL diff --git a/src/bash/Files/plugin.c b/src/bash/Files/plugin.c deleted file mode 100644 index 2dd9aaaca873..000000000000 --- a/src/bash/Files/plugin.c +++ /dev/null @@ -1,394 +0,0 @@ -/* plugin.c -- Bash plugin support. */ - -/* Copyright (C) 1987-2016 Free Software Foundation, Inc. - - This file is part of GNU Bash, the Bourne Again SHell. - - Bash is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Bash is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Bash. If not, see . -*/ - -#include "config.h" - -#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX) - #pragma alloca -#endif /* _AIX && RISC6000 && !__GNUC__ */ - -// disable bash memory management when build for UT, PTR_T defined in xmalloc.h, define here for disable warning -#if defined (BASH_PLUGIN_UT) -# define _XMALLOC_H_ -# define PTR_T void * -# define malloc mock_malloc -# define free mock_free -#else -#endif - -#include -#include -#include "chartypes.h" -#include "bashtypes.h" -#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H) -# include -#endif -#include "filecntl.h" -#include "posixstat.h" -#include -#if defined (HAVE_SYS_PARAM_H) -# include -#endif - -#if defined (HAVE_UNISTD_H) -# include -#endif - -#include "posixtime.h" - -#if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE) -# include -#endif - -#if defined (HAVE_SYS_TIMES_H) && defined (HAVE_TIMES) -# include -#endif - -#include - -#if !defined (errno) -extern int errno; -#endif - -#define NEED_FPURGE_DECL -#define NEED_SH_SETLINEBUF_DECL - -#include "bashansi.h" -#include "bashintl.h" - -#include "shell.h" -#include /* use <...> so we pick it up from the build directory */ -#include "error.h" -#include "flags.h" -#include "builtins.h" -#include "hashlib.h" -#include "jobs.h" -#include "execute_cmd.h" -#include "findcmd.h" -#include "redir.h" -#include "trap.h" -#include "pathexp.h" -#include "hashcmd.h" - - -#if defined (BASH_SHELL_EXECVE_PLUGIN) -#include "plugin.h" -#endif /* BASH_SHELL_EXECVE_PLUGIN */ - -#if defined (COND_COMMAND) -# include "test.h" -#endif - -#include "builtins/common.h" - -#include "builtins/getopt.h" - -#include -#include - -#if defined (BUFFERED_INPUT) -# include "input.h" -#endif - -#if defined (ALIAS) -# include "alias.h" -#endif - -#if defined (HISTORY) -# include "bashhist.h" -#endif - -#if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR) -# include /* mbschr */ -#endif - -/* plugin configration file */ -const char *plugin_config_file = "/etc/bash_plugins.conf"; - -/* plugin on_shell_execve function name */ -static const char *on_shell_execve_function_name = "on_shell_execve"; - -/* plugin plugin_init function name */ -static const char *plugin_init_function_name = "plugin_init"; - -/* plugin plugin_uninit function name */ -static const char *plugin_uninit_function_name = "plugin_uninit"; - -/* plugin handle for test */ -PLUGIN_NODE *global_plugin_list = NULL; - -/* Load plugin by plugin path */ -void -append_plugin( - void *plugin_handle, - on_shell_execve_t *on_shell_execve, - plugin_init_t *plugin_init, - plugin_uninit_t *plugin_uninit) -{ - /* Create and initialize new plugin */ - PLUGIN_NODE *new_plugin_node = (PLUGIN_NODE*)malloc(sizeof(PLUGIN_NODE)); - new_plugin_node->next = NULL; - new_plugin_node->plugin_handle = plugin_handle; - new_plugin_node->on_shell_execve = on_shell_execve; - new_plugin_node->plugin_init = plugin_init; - new_plugin_node->plugin_uninit = plugin_uninit; - -#ifdef DEBUG - itrace("Plugin: append plugin node %p to global list %p\n", new_plugin_node, global_plugin_list); -#endif - - /* Find the pointer to the latest plugin node's 'next' field */ - PLUGIN_NODE **current_plugin_node = &global_plugin_list; - while (*current_plugin_node != NULL) { - current_plugin_node = &((*current_plugin_node)->next); - -#ifdef DEBUG - itrace("Plugin: founded next plugin node: %p\n", *current_plugin_node); -#endif - } - - /* append new plugin to tail node */ - *current_plugin_node = new_plugin_node; - -#ifdef DEBUG - itrace("Plugin: append new plugin node %p to %p\n", new_plugin_node, current_plugin_node); -#endif -} - - -/* Load plugin by plugin path */ -void -try_load_plugin_by_path(const char *plugin_path) -{ - /* Plugin handle */ - void *plugin_handle; - if ( (plugin_handle = dlopen(plugin_path, RTLD_LAZY)) == NULL) { -#ifdef DEBUG - itrace("Plugin: can't load plugin %s: %s\n", plugin_path, dlerror()); -#endif - return; - } - - /* Check if plugin support shell execve method */ - on_shell_execve_t* plugin_on_shell_execve_handle = dlsym(plugin_handle, on_shell_execve_function_name); - if (dlerror() != NULL) { - dlclose(plugin_handle); - -#ifdef DEBUG - itrace("Plugin: can't find on_shell_execve function %s: %s\n", plugin_path, dlerror()); -#endif - return; - } - - - /* Check if plugin support un-initialization method */ - plugin_uninit_t* plugin_uninit_handle = dlsym(plugin_handle, plugin_uninit_function_name); - if (dlerror() != NULL) { - dlclose(plugin_handle); - -#ifdef DEBUG - itrace("Plugin: can't find plugin_uninit function %s: %s\n", plugin_path, dlerror()); -#endif - return; - } - - /* Check if plugin support initialization method */ - plugin_init_t* plugin_init_handle = dlsym(plugin_handle, plugin_init_function_name); - if (dlerror() != NULL) { - dlclose(plugin_handle); - -#ifdef DEBUG - itrace("Plugin: can't find plugin_init function %s: %s\n", plugin_path, dlerror()); -#endif - return; - } - else { - /* Initialize plugin */ - plugin_init_handle(); - } - - /* Add plugin to plugin list */ - append_plugin(plugin_handle, - plugin_on_shell_execve_handle, - plugin_init_handle, - plugin_uninit_handle); - -#ifdef DEBUG - itrace("Plugin: plugin %s loaded\n", plugin_path); -#endif -} - -/* Load plugin by config file */ -void -load_plugin_by_config(const char *config_filename) -{ - FILE *config_file; - char buffer[256]; - - config_file = fopen(config_filename, "r"); - if(config_file == NULL) { -#ifdef DEBUG - itrace("Plugin: can't open plugin config file %s: %s\n", config_filename, strerror(errno)); -#endif - return; - } - - while(fgets(buffer, sizeof buffer, config_file)) { - if(*buffer == '#' || isspace(*buffer)) { - /* ignore comments or white space. */ - continue; - } - - /* read to first whitespace. */ - strtok(buffer, " \t\n\r\f"); - - if(!strncmp(buffer, "plugin=", 7)) { - /* read plugin path. */ - char* plugin_path = strtok(buffer+7, " \t\n\r\f"); -#ifdef DEBUG - itrace("Plugin: load plugin: %s\n", plugin_path); -#endif - try_load_plugin_by_path(plugin_path); - } -#ifdef DEBUG - else { - /* output debug message. */ - itrace("Plugin: unrecognized parameter: %s\n", buffer); - } -#endif - } - - fclose(config_file); -} - -/* Free loaded plugins */ -void -free_loaded_plugins() -{ - if (global_plugin_list == NULL) { - return; - } - -#ifdef DEBUG - itrace("Plugin: start free plugin from global list %p\n", global_plugin_list); -#endif - - /* Walk to last plugin */ - PLUGIN_NODE *next_plugin_node = global_plugin_list; - while (next_plugin_node != NULL) { - - /* Unload plugin */ - next_plugin_node->plugin_uninit(); - dlclose(next_plugin_node->plugin_handle); - - /* Continue with next pligin */ - PLUGIN_NODE* current_plugin_node_memory = next_plugin_node; - next_plugin_node = next_plugin_node->next; - -#ifdef DEBUG - itrace("Plugin: next plugin address %p\n", next_plugin_node); -#endif - - /* Free plugin node memory, this may also reset all allocated memory depends on c lib implementation */ - free(current_plugin_node_memory); - } - - /* Reset plugin list */ - global_plugin_list = NULL; -} - -/* Invoke loaded plugins */ -int -invoke_loaded_plugins (user, shell_level, cmd, argv) - char *user; - int shell_level; - char *cmd; - char **argv; -{ - if (global_plugin_list == NULL) { - return 0; - } - -#ifdef DEBUG - itrace("Plugin: start invoke plugin from global list %p\n", global_plugin_list); -#endif - - /* Walk to last plugin */ - PLUGIN_NODE *next_plugin_node = global_plugin_list; - while (next_plugin_node != NULL) { - - /* Call plugin method */ - int plugin_error_code = next_plugin_node->on_shell_execve(user, shell_level, cmd, argv); - if (plugin_error_code != 0) { -#ifdef DEBUG - itrace("Plugin: on_execve return error: %d\n", plugin_error_code); -#endif - /* Exit when plugin failed */ - return plugin_error_code; - } - - /* Continue with next pligin */ - next_plugin_node = next_plugin_node->next; - -#ifdef DEBUG - itrace("Plugin: next plugin address %p\n", next_plugin_node); -#endif - } - - return 0; -} - -/* Load all plugins。 */ -void -load_plugins () -{ - load_plugin_by_config(plugin_config_file); -} - -/* Free all plugins */ -void -free_plugins () -{ - free_loaded_plugins(); -} - -/* Invoke plugins before shell execve */ -int -invoke_plugin_on_shell_execve (user, cmd, argv) - char *user; - char *cmd; - char **argv; -{ - const char* shell_level_str = get_string_value ("SHLVL"); - const int shell_level = atoi (shell_level_str); - - if (absolute_program (cmd)) { - // find real path for relative path command - char resolved_path[PATH_MAX]; - - // real_path_buffer should not free here because we pass resolved_path as parameter. - char* real_path_buffer = realpath(cmd, resolved_path); - - return invoke_loaded_plugins(user, shell_level, resolved_path, argv); - } - else { - return invoke_loaded_plugins(user, shell_level, cmd, argv); - } -} diff --git a/src/bash/Files/plugin.h b/src/bash/Files/plugin.h deleted file mode 100644 index 5aa5e67f53c1..000000000000 --- a/src/bash/Files/plugin.h +++ /dev/null @@ -1,75 +0,0 @@ -/* plugin.h - functions from plugin.c. */ - -/* Copyright (C) 1993-2015 Free Software Foundation, Inc. - - This file is part of GNU Bash, the Bourne Again SHell. - - Bash is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Bash is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Bash. If not, see . -*/ - -#if !defined (_PLUGIN_H_) -#define _PLUGIN_H_ - -#include "stdc.h" - -/* System-wide bash plugin configuration. */ -#define SYS_BASH_PLUGIN "/etc/bash.plugin" - -typedef enum { T_COMMAND } plugin_type_t; - -/* Bash plugin config. */ -typedef struct bash_plugin_conf -{ - const char *path; /* path to binary */ - char *name; /* Used to distinguish plugins */ -} bash_plugin_conf_t; - -/* plugin on_shell_execve function handle type */ -typedef int on_shell_execve_t (char *user, int shell_level, char *cmd, char **argv); - -/* plugin plugin_init function handle type */ -typedef int plugin_init_t (); - -/* plugin plugin_uninit function handle type */ -typedef int plugin_uninit_t (); - -/* Plugin list node. */ -typedef struct plugin_node { - - /* Next plugin pointer. */ - struct plugin_node *next; - - /* Plugin library handle. */ - void *plugin_handle; - - /* Plugin on_shell_execve function handle. */ - on_shell_execve_t *on_shell_execve; - - /* Plugin plugin_init function handle. */ - plugin_init_t *plugin_init; - - /* Plugin plugin_uninit function handle. */ - plugin_uninit_t *plugin_uninit; -} PLUGIN_NODE; - -/* Load all plugins */ -extern void load_plugins __P((void)); - -/* Free all plugins */ -extern void free_plugins __P((void)); - -/* Invoke plugins before shell execve */ -extern int invoke_plugin_on_shell_execve __P((char *, char *, char **)); - -#endif /* _PLUGIN_H_ */ diff --git a/src/bash/patches/0001-Add-plugin-support-to-bash.patch b/src/bash/patches/0001-Add-plugin-support-to-bash.patch index 5384120433c7..d2dbf318463b 100644 --- a/src/bash/patches/0001-Add-plugin-support-to-bash.patch +++ b/src/bash/patches/0001-Add-plugin-support-to-bash.patch @@ -1,16 +1,20 @@ -From bbb54228ffc084da4eea01e9227d4f0f96a1f814 Mon Sep 17 00:00:00 2001 +From 11df0bddd65c84af9c4015489bf652b9d6e68fa9 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Fri, 3 Sep 2021 14:05:36 +0800 Subject: [PATCH] Add plugin support to bash. --- - Makefile.in | 14 +++++++++----- - config.h.in | 3 +++ - configure | 18 ++++++++++++++---- - configure.ac | 10 ++++++++++ - execute_cmd.c | 12 ++++++++++++ - shell.c | 12 ++++++++++++ - 6 files changed, 60 insertions(+), 9 deletions(-) + Makefile.in | 14 +- + config.h.in | 3 + + configure | 18 ++- + configure.ac | 10 ++ + execute_cmd.c | 15 ++ + plugin.c | 421 ++++++++++++++++++++++++++++++++++++++++++++++++++ + plugin.h | 75 +++++++++ + shell.c | 12 ++ + 8 files changed, 559 insertions(+), 9 deletions(-) + create mode 100644 plugin.c + create mode 100644 plugin.h diff --git a/Makefile.in b/Makefile.in index 5fcb44b..9e4e4c3 100644 @@ -207,7 +211,7 @@ index 52b4cdb..8070b94 100644 AC_DEFINE(ALIAS) fi diff --git a/execute_cmd.c b/execute_cmd.c -index 8b3c83a..b7157aa 100644 +index 8b3c83a..8e1920b 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -82,6 +82,10 @@ extern int errno; @@ -221,7 +225,7 @@ index 8b3c83a..b7157aa 100644 #include "builtins/common.h" #include "builtins/builtext.h" /* list of builtins */ -@@ -5458,6 +5462,14 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, +@@ -5458,6 +5462,17 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, leave it there, in the same format that the user used to type it in. */ args = strvec_from_word_list (words, 0, 0, (int *)NULL); @@ -229,6 +233,9 @@ index 8b3c83a..b7157aa 100644 +#if defined (BASH_SHELL_EXECVE_PLUGIN) + result = invoke_plugin_on_shell_execve (current_user.user_name, command, args); + if (result) { ++#if defined (DEBUG) ++ itrace("invoke_plugin_on_shell_execve: failed invoke plugin with user:%s, command:%s", current_user.user_name, command); ++#endif + exit (EXECUTION_FAILURE); + } +#endif /* BASH_SHELL_EXECVE_PLUGIN */ @@ -236,8 +243,516 @@ index 8b3c83a..b7157aa 100644 exit (shell_execve (command, args, export_env)); } else +diff --git a/plugin.c b/plugin.c +new file mode 100644 +index 0000000..2bfdf5a +--- /dev/null ++++ b/plugin.c +@@ -0,0 +1,421 @@ ++/* plugin.c -- Bash plugin support. */ ++ ++/* Copyright (C) 1987-2016 Free Software Foundation, Inc. ++ ++ This file is part of GNU Bash, the Bourne Again SHell. ++ ++ Bash is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. ++ ++ Bash is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with Bash. If not, see . ++*/ ++ ++#include "config.h" ++ ++#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX) ++ #pragma alloca ++#endif /* _AIX && RISC6000 && !__GNUC__ */ ++ ++// disable bash memory management when build for UT, PTR_T defined in xmalloc.h, define here for disable warning ++#if defined (BASH_PLUGIN_UT) ++# define _XMALLOC_H_ ++# define PTR_T void * ++# define malloc mock_malloc ++# define free mock_free ++#else ++#endif ++ ++#include ++#include ++#include "chartypes.h" ++#include "bashtypes.h" ++#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H) ++# include ++#endif ++#include "filecntl.h" ++#include "posixstat.h" ++#include ++#if defined (HAVE_SYS_PARAM_H) ++# include ++#endif ++ ++#if defined (HAVE_UNISTD_H) ++# include ++#endif ++ ++#include "posixtime.h" ++ ++#if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE) ++# include ++#endif ++ ++#if defined (HAVE_SYS_TIMES_H) && defined (HAVE_TIMES) ++# include ++#endif ++ ++#include ++ ++#if !defined (errno) ++extern int errno; ++#endif ++ ++#define NEED_FPURGE_DECL ++#define NEED_SH_SETLINEBUF_DECL ++ ++#include "bashansi.h" ++#include "bashintl.h" ++ ++#include "shell.h" ++#include /* use <...> so we pick it up from the build directory */ ++#include "error.h" ++#include "flags.h" ++#include "builtins.h" ++#include "hashlib.h" ++#include "jobs.h" ++#include "execute_cmd.h" ++#include "findcmd.h" ++#include "redir.h" ++#include "trap.h" ++#include "pathexp.h" ++#include "hashcmd.h" ++ ++ ++#if defined (BASH_SHELL_EXECVE_PLUGIN) ++#include "plugin.h" ++#endif /* BASH_SHELL_EXECVE_PLUGIN */ ++ ++#if defined (COND_COMMAND) ++# include "test.h" ++#endif ++ ++#include "builtins/common.h" ++ ++#include "builtins/getopt.h" ++ ++#include ++#include ++ ++#if defined (BUFFERED_INPUT) ++# include "input.h" ++#endif ++ ++#if defined (ALIAS) ++# include "alias.h" ++#endif ++ ++#if defined (HISTORY) ++# include "bashhist.h" ++#endif ++ ++#if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR) ++# include /* mbschr */ ++#endif ++ ++/* configuration buffer size */ ++#define CONFIG_BUFFER_SIZE 256 ++ ++/* configuration plugin setting key */ ++#define CONFIG_PLUGIN_SETTING_KEY "plugin=" ++ ++/* configuration termination characters */ ++#define CONFIG_SETTING_TERMINATIONS " \t\n\r\f" ++ ++/* configuration comments start character */ ++#define CONFIG_SETTING_COMMENTS_START_CHAR '#' ++ ++/* plugin configration file */ ++const char *plugin_config_file = "/etc/bash_plugins.conf"; ++ ++/* plugin on_shell_execve function name */ ++static const char *on_shell_execve_function_name = "on_shell_execve"; ++ ++/* plugin plugin_init function name */ ++static const char *plugin_init_function_name = "plugin_init"; ++ ++/* plugin plugin_uninit function name */ ++static const char *plugin_uninit_function_name = "plugin_uninit"; ++ ++/* plugin handle for test */ ++PLUGIN_NODE *global_plugin_list = NULL; ++ ++/* Load plugin by plugin path */ ++void ++append_plugin( ++ plugin_handle, ++ on_shell_execve, ++ plugin_init, ++ plugin_uninit) ++ void *plugin_handle; ++ on_shell_execve_t *on_shell_execve; ++ plugin_init_t *plugin_init; ++ plugin_uninit_t *plugin_uninit; ++{ ++ /* Create and initialize new plugin */ ++ PLUGIN_NODE *new_plugin_node = (PLUGIN_NODE*)malloc(sizeof(PLUGIN_NODE)); ++ if (new_plugin_node == NULL) ++ { ++ /* When allocate memory failed, stop and return. */ ++#ifdef DEBUG ++ itrace("Plugin: failed to allocate memory for plugin node.\n"); ++#endif ++ return; ++ } ++ ++ new_plugin_node->next = NULL; ++ new_plugin_node->plugin_handle = plugin_handle; ++ new_plugin_node->on_shell_execve = on_shell_execve; ++ new_plugin_node->plugin_init = plugin_init; ++ new_plugin_node->plugin_uninit = plugin_uninit; ++ ++#ifdef DEBUG ++ itrace("Plugin: append plugin node %p to global list %p\n", new_plugin_node, global_plugin_list); ++#endif ++ ++ /* Find the pointer to the latest plugin node's 'next' field */ ++ PLUGIN_NODE **current_plugin_node = &global_plugin_list; ++ while (*current_plugin_node != NULL) { ++ current_plugin_node = &((*current_plugin_node)->next); ++ ++#ifdef DEBUG ++ itrace("Plugin: founded next plugin node: %p\n", *current_plugin_node); ++#endif ++ } ++ ++ /* append new plugin to tail node */ ++ *current_plugin_node = new_plugin_node; ++ ++#ifdef DEBUG ++ itrace("Plugin: append new plugin node %p to %p\n", new_plugin_node, current_plugin_node); ++#endif ++} ++ ++ ++/* Load plugin by plugin path */ ++void ++try_load_plugin_by_path(plugin_path) ++ const char *plugin_path; ++{ ++ /* Plugin handle */ ++ void *plugin_handle; ++ if ( (plugin_handle = dlopen(plugin_path, RTLD_LAZY)) == NULL) { ++#ifdef DEBUG ++ itrace("Plugin: can't load plugin %s: %s\n", plugin_path, dlerror()); ++#endif ++ return; ++ } ++ ++ /* Check if plugin support shell execve method */ ++ on_shell_execve_t* plugin_on_shell_execve_handle = dlsym(plugin_handle, on_shell_execve_function_name); ++ if (dlerror() != NULL) { ++ dlclose(plugin_handle); ++ ++#ifdef DEBUG ++ itrace("Plugin: can't find on_shell_execve function %s: %s\n", plugin_path, dlerror()); ++#endif ++ return; ++ } ++ ++ ++ /* Check if plugin support un-initialization method */ ++ plugin_uninit_t* plugin_uninit_handle = dlsym(plugin_handle, plugin_uninit_function_name); ++ if (dlerror() != NULL) { ++ dlclose(plugin_handle); ++ ++#ifdef DEBUG ++ itrace("Plugin: can't find plugin_uninit function %s: %s\n", plugin_path, dlerror()); ++#endif ++ return; ++ } ++ ++ /* Check if plugin support initialization method */ ++ plugin_init_t* plugin_init_handle = dlsym(plugin_handle, plugin_init_function_name); ++ if (dlerror() != NULL) { ++ dlclose(plugin_handle); ++ ++#ifdef DEBUG ++ itrace("Plugin: can't find plugin_init function %s: %s\n", plugin_path, dlerror()); ++#endif ++ return; ++ } ++ else { ++ /* Initialize plugin */ ++ plugin_init_handle(); ++ } ++ ++ /* Add plugin to plugin list */ ++ append_plugin(plugin_handle, ++ plugin_on_shell_execve_handle, ++ plugin_init_handle, ++ plugin_uninit_handle); ++ ++#ifdef DEBUG ++ itrace("Plugin: plugin %s loaded\n", plugin_path); ++#endif ++} ++ ++/* Load plugin by config file */ ++void ++load_plugin_by_config(config_filename) ++ const char *config_filename; ++{ ++ FILE *config_file; ++ char buffer[CONFIG_BUFFER_SIZE]; ++ ++ config_file = fopen(config_filename, "r"); ++ if(config_file == NULL) { ++#ifdef DEBUG ++ itrace("Plugin: can't open plugin config file %s: %s\n", config_filename, strerror(errno)); ++#endif ++ return; ++ } ++ ++ while(fgets(buffer, sizeof buffer, config_file)) { ++ if(*buffer == CONFIG_SETTING_COMMENTS_START_CHAR || isspace(*buffer)) { ++ /* ignore comments or white space. */ ++ continue; ++ } ++ ++ /* read to first whitespace. */ ++ strtok(buffer, CONFIG_SETTING_TERMINATIONS); ++ ++ if(!strncmp(buffer, CONFIG_PLUGIN_SETTING_KEY, strlen(CONFIG_PLUGIN_SETTING_KEY))) { ++ /* read plugin path. */ ++ char* plugin_path = strtok(buffer + strlen(CONFIG_PLUGIN_SETTING_KEY), CONFIG_SETTING_TERMINATIONS); ++#ifdef DEBUG ++ itrace("Plugin: load plugin: %s\n", plugin_path); ++#endif ++ try_load_plugin_by_path(plugin_path); ++ } ++#ifdef DEBUG ++ else { ++ /* output debug message. */ ++ itrace("Plugin: unrecognized parameter: %s\n", buffer); ++ } ++#endif ++ } ++ ++ fclose(config_file); ++} ++ ++/* Free loaded plugins */ ++void ++free_loaded_plugins() ++{ ++ if (global_plugin_list == NULL) { ++ return; ++ } ++ ++#ifdef DEBUG ++ itrace("Plugin: start free plugin from global list %p\n", global_plugin_list); ++#endif ++ ++ /* Walk to last plugin */ ++ PLUGIN_NODE *next_plugin_node = global_plugin_list; ++ while (next_plugin_node != NULL) { ++ ++ /* Unload plugin */ ++ next_plugin_node->plugin_uninit(); ++ dlclose(next_plugin_node->plugin_handle); ++ ++ /* Continue with next pligin */ ++ PLUGIN_NODE* current_plugin_node_memory = next_plugin_node; ++ next_plugin_node = next_plugin_node->next; ++ ++#ifdef DEBUG ++ itrace("Plugin: next plugin address %p\n", next_plugin_node); ++#endif ++ ++ /* Free plugin node memory, this may also reset all allocated memory depends on c lib implementation */ ++ free(current_plugin_node_memory); ++ } ++ ++ /* Reset plugin list */ ++ global_plugin_list = NULL; ++} ++ ++/* Invoke loaded plugins */ ++int ++invoke_loaded_plugins (user, shell_level, cmd, argv) ++ char *user; ++ int shell_level; ++ char *cmd; ++ char **argv; ++{ ++ if (global_plugin_list == NULL) { ++ return 0; ++ } ++ ++#ifdef DEBUG ++ itrace("Plugin: start invoke plugin from global list %p\n", global_plugin_list); ++#endif ++ ++ /* Walk to last plugin */ ++ PLUGIN_NODE *next_plugin_node = global_plugin_list; ++ while (next_plugin_node != NULL) { ++ ++ /* Call plugin method */ ++ int plugin_error_code = next_plugin_node->on_shell_execve(user, shell_level, cmd, argv); ++ if (plugin_error_code != 0) { ++#ifdef DEBUG ++ itrace("Plugin: on_execve return error: %d\n", plugin_error_code); ++#endif ++ /* Exit when plugin failed */ ++ return plugin_error_code; ++ } ++ ++ /* Continue with next pligin */ ++ next_plugin_node = next_plugin_node->next; ++ ++#ifdef DEBUG ++ itrace("Plugin: next plugin address %p\n", next_plugin_node); ++#endif ++ } ++ ++ return 0; ++} ++ ++/* Load all plugins。 */ ++void ++load_plugins () ++{ ++ load_plugin_by_config(plugin_config_file); ++} ++ ++/* Free all plugins */ ++void ++free_plugins () ++{ ++ free_loaded_plugins(); ++} ++ ++/* Invoke plugins before shell execve */ ++int ++invoke_plugin_on_shell_execve (user, cmd, argv) ++ char *user; ++ char *cmd; ++ char **argv; ++{ ++ const char* shell_level_str = get_string_value ("SHLVL"); ++ const int shell_level = atoi (shell_level_str); ++ ++ if (absolute_program (cmd)) { ++ // find real path for relative path command ++ char resolved_path[PATH_MAX]; ++ ++ // real_path_buffer should not free here because we pass resolved_path as parameter. ++ char* real_path_buffer = realpath(cmd, resolved_path); ++ ++ return invoke_loaded_plugins(user, shell_level, resolved_path, argv); ++ } ++ else { ++ return invoke_loaded_plugins(user, shell_level, cmd, argv); ++ } ++} +diff --git a/plugin.h b/plugin.h +new file mode 100644 +index 0000000..5aa5e67 +--- /dev/null ++++ b/plugin.h +@@ -0,0 +1,75 @@ ++/* plugin.h - functions from plugin.c. */ ++ ++/* Copyright (C) 1993-2015 Free Software Foundation, Inc. ++ ++ This file is part of GNU Bash, the Bourne Again SHell. ++ ++ Bash is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. ++ ++ Bash is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with Bash. If not, see . ++*/ ++ ++#if !defined (_PLUGIN_H_) ++#define _PLUGIN_H_ ++ ++#include "stdc.h" ++ ++/* System-wide bash plugin configuration. */ ++#define SYS_BASH_PLUGIN "/etc/bash.plugin" ++ ++typedef enum { T_COMMAND } plugin_type_t; ++ ++/* Bash plugin config. */ ++typedef struct bash_plugin_conf ++{ ++ const char *path; /* path to binary */ ++ char *name; /* Used to distinguish plugins */ ++} bash_plugin_conf_t; ++ ++/* plugin on_shell_execve function handle type */ ++typedef int on_shell_execve_t (char *user, int shell_level, char *cmd, char **argv); ++ ++/* plugin plugin_init function handle type */ ++typedef int plugin_init_t (); ++ ++/* plugin plugin_uninit function handle type */ ++typedef int plugin_uninit_t (); ++ ++/* Plugin list node. */ ++typedef struct plugin_node { ++ ++ /* Next plugin pointer. */ ++ struct plugin_node *next; ++ ++ /* Plugin library handle. */ ++ void *plugin_handle; ++ ++ /* Plugin on_shell_execve function handle. */ ++ on_shell_execve_t *on_shell_execve; ++ ++ /* Plugin plugin_init function handle. */ ++ plugin_init_t *plugin_init; ++ ++ /* Plugin plugin_uninit function handle. */ ++ plugin_uninit_t *plugin_uninit; ++} PLUGIN_NODE; ++ ++/* Load all plugins */ ++extern void load_plugins __P((void)); ++ ++/* Free all plugins */ ++extern void free_plugins __P((void)); ++ ++/* Invoke plugins before shell execve */ ++extern int invoke_plugin_on_shell_execve __P((char *, char *, char **)); ++ ++#endif /* _PLUGIN_H_ */ diff --git a/shell.c b/shell.c -index a2b2a55..237afbb 100644 +index a2b2a55..1eedf31 100644 --- a/shell.c +++ b/shell.c @@ -46,6 +46,10 @@ @@ -256,7 +771,7 @@ index a2b2a55..237afbb 100644 run_shopt_alist (); +#if defined (BASH_SHELL_EXECVE_PLUGIN) -+ load_plugins (); ++ load_plugins (); +#endif /* BASH_SHELL_EXECVE_PLUGIN */ + /* From here on in, the shell must be a normal functioning shell. @@ -268,7 +783,7 @@ index a2b2a55..237afbb 100644 exit_shell (last_command_exit_value); + +#if defined (BASH_SHELL_EXECVE_PLUGIN) -+ free_plugins (); ++ free_plugins (); +#endif /* BASH_SHELL_EXECVE_PLUGIN */ } From ff0af031fdfab94887611f376babe88f6faa802e Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Mon, 6 Sep 2021 16:52:11 +0800 Subject: [PATCH 12/24] Install patched bash package. --- files/build_templates/sonic_debian_extension.j2 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 index 0d5b895cacfe..45286629f38d 100644 --- a/files/build_templates/sonic_debian_extension.j2 +++ b/files/build_templates/sonic_debian_extension.j2 @@ -265,6 +265,10 @@ sudo rm -rf $FILESYSTEM_ROOT/$SONIC_UTILITIES_PY3_WHEEL_NAME sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/sonic-utilities-data_*.deb || \ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f +# Install customized bash version to patch bash plugin support. +sudo dpkg --root=$FILESYSTEM_ROOT -i target/debs/bash_*.deb || \ + sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f + # sonic-utilities-data installs bash-completion as a dependency. However, it is disabled by default # in bash.bashrc, so we copy a version of the file with it enabled here. sudo cp -f $IMAGE_CONFIGS/bash/bash.bashrc $FILESYSTEM_ROOT/etc/ From 1b46066a566f9136a9033ebae28f73901128ab97 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Thu, 9 Sep 2021 11:08:08 +0800 Subject: [PATCH 13/24] Use quilt to manage patches. --- src/bash/Makefile | 6 +- .../0001-Add-plugin-support-to-bash.patch | 68 +++++++++---------- src/bash/patches/series | 1 + 3 files changed, 37 insertions(+), 38 deletions(-) create mode 100644 src/bash/patches/series diff --git a/src/bash/Makefile b/src/bash/Makefile index 16acfa02f71d..7c0f5c72d4b7 100644 --- a/src/bash/Makefile +++ b/src/bash/Makefile @@ -9,17 +9,15 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : dget -u https://launchpad.net/debian/+archive/primary/+sourcefiles/bash/$(BASH_VERSION_FULL)/bash_$(BASH_VERSION_FULL).dsc + # Apply plugin suport patches + quilt push -a pushd bash-$(BASH_VERSION_MAJOR) - - # Apply plugin suport patch - patch -p1 < ../patches/0001-Add-plugin-support-to-bash.patch # copy UT and source code. cp -a ../Files/. ./ # build package DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) - popd mv $* $(DEST)/ diff --git a/src/bash/patches/0001-Add-plugin-support-to-bash.patch b/src/bash/patches/0001-Add-plugin-support-to-bash.patch index d2dbf318463b..f764aa206a89 100644 --- a/src/bash/patches/0001-Add-plugin-support-to-bash.patch +++ b/src/bash/patches/0001-Add-plugin-support-to-bash.patch @@ -1,25 +1,25 @@ -From 11df0bddd65c84af9c4015489bf652b9d6e68fa9 Mon Sep 17 00:00:00 2001 +From 8db363a7408976b808e9b2fc79549322381dc37a Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> -Date: Fri, 3 Sep 2021 14:05:36 +0800 +Date: Thu, 9 Sep 2021 11:04:13 +0800 Subject: [PATCH] Add plugin support to bash. --- - Makefile.in | 14 +- - config.h.in | 3 + - configure | 18 ++- - configure.ac | 10 ++ - execute_cmd.c | 15 ++ - plugin.c | 421 ++++++++++++++++++++++++++++++++++++++++++++++++++ - plugin.h | 75 +++++++++ - shell.c | 12 ++ + bash-5.0/Makefile.in | 14 +- + bash-5.0/config.h.in | 3 + + bash-5.0/configure | 18 +- + bash-5.0/configure.ac | 10 + + bash-5.0/execute_cmd.c | 15 ++ + bash-5.0/plugin.c | 421 +++++++++++++++++++++++++++++++++++++++++ + bash-5.0/plugin.h | 75 ++++++++ + bash-5.0/shell.c | 12 ++ 8 files changed, 559 insertions(+), 9 deletions(-) - create mode 100644 plugin.c - create mode 100644 plugin.h + create mode 100644 bash-5.0/plugin.c + create mode 100644 bash-5.0/plugin.h -diff --git a/Makefile.in b/Makefile.in +diff --git a/bash-5.0/Makefile.in b/bash-5.0/Makefile.in index 5fcb44b..9e4e4c3 100644 ---- a/Makefile.in -+++ b/Makefile.in +--- a/bash-5.0/Makefile.in ++++ b/bash-5.0/Makefile.in @@ -379,6 +379,9 @@ LTLIBINTL = @LTLIBINTL@ INTLLIBS = @INTLLIBS@ INTLOBJS = @INTLOBJS@ @@ -83,10 +83,10 @@ index 5fcb44b..9e4e4c3 100644 expr.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h expr.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h expr.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h -diff --git a/config.h.in b/config.h.in +diff --git a/bash-5.0/config.h.in b/bash-5.0/config.h.in index 8554aec..7f17024 100644 ---- a/config.h.in -+++ b/config.h.in +--- a/bash-5.0/config.h.in ++++ b/bash-5.0/config.h.in @@ -38,6 +38,9 @@ BSD-like job control. */ #undef JOB_CONTROL @@ -97,10 +97,10 @@ index 8554aec..7f17024 100644 /* Define ALIAS if you want the alias features. */ #undef ALIAS -diff --git a/configure b/configure +diff --git a/bash-5.0/configure b/bash-5.0/configure index 2f62662..cae212f 100644 ---- a/configure -+++ b/configure +--- a/bash-5.0/configure ++++ b/bash-5.0/configure @@ -630,6 +630,7 @@ LOCAL_DEFS LOCAL_LDFLAGS LOCAL_CFLAGS @@ -168,10 +168,10 @@ index 2f62662..cae212f 100644 if test $opt_alias = yes; then $as_echo "#define ALIAS 1" >>confdefs.h -diff --git a/configure.ac b/configure.ac +diff --git a/bash-5.0/configure.ac b/bash-5.0/configure.ac index 52b4cdb..8070b94 100644 ---- a/configure.ac -+++ b/configure.ac +--- a/bash-5.0/configure.ac ++++ b/bash-5.0/configure.ac @@ -185,6 +185,7 @@ opt_dircomplete_expand_default=no opt_globascii_default=yes opt_function_import=yes @@ -210,10 +210,10 @@ index 52b4cdb..8070b94 100644 if test $opt_alias = yes; then AC_DEFINE(ALIAS) fi -diff --git a/execute_cmd.c b/execute_cmd.c +diff --git a/bash-5.0/execute_cmd.c b/bash-5.0/execute_cmd.c index 8b3c83a..8e1920b 100644 ---- a/execute_cmd.c -+++ b/execute_cmd.c +--- a/bash-5.0/execute_cmd.c ++++ b/bash-5.0/execute_cmd.c @@ -82,6 +82,10 @@ extern int errno; # include "test.h" #endif @@ -243,11 +243,11 @@ index 8b3c83a..8e1920b 100644 exit (shell_execve (command, args, export_env)); } else -diff --git a/plugin.c b/plugin.c +diff --git a/bash-5.0/plugin.c b/bash-5.0/plugin.c new file mode 100644 index 0000000..2bfdf5a --- /dev/null -+++ b/plugin.c ++++ b/bash-5.0/plugin.c @@ -0,0 +1,421 @@ +/* plugin.c -- Bash plugin support. */ + @@ -670,11 +670,11 @@ index 0000000..2bfdf5a + return invoke_loaded_plugins(user, shell_level, cmd, argv); + } +} -diff --git a/plugin.h b/plugin.h +diff --git a/bash-5.0/plugin.h b/bash-5.0/plugin.h new file mode 100644 index 0000000..5aa5e67 --- /dev/null -+++ b/plugin.h ++++ b/bash-5.0/plugin.h @@ -0,0 +1,75 @@ +/* plugin.h - functions from plugin.c. */ + @@ -751,10 +751,10 @@ index 0000000..5aa5e67 +extern int invoke_plugin_on_shell_execve __P((char *, char *, char **)); + +#endif /* _PLUGIN_H_ */ -diff --git a/shell.c b/shell.c +diff --git a/bash-5.0/shell.c b/bash-5.0/shell.c index a2b2a55..1eedf31 100644 ---- a/shell.c -+++ b/shell.c +--- a/bash-5.0/shell.c ++++ b/bash-5.0/shell.c @@ -46,6 +46,10 @@ # include #endif diff --git a/src/bash/patches/series b/src/bash/patches/series new file mode 100644 index 000000000000..a27ad05ca28b --- /dev/null +++ b/src/bash/patches/series @@ -0,0 +1 @@ +0001-Add-plugin-support-to-bash.patch \ No newline at end of file From 3cfd4ce97e76179b15564f4ea78dab2c4ce613a0 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Thu, 9 Sep 2021 12:20:32 +0800 Subject: [PATCH 14/24] Fix PR comments --- .../0001-Add-plugin-support-to-bash.patch | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/bash/patches/0001-Add-plugin-support-to-bash.patch b/src/bash/patches/0001-Add-plugin-support-to-bash.patch index f764aa206a89..b22be978535a 100644 --- a/src/bash/patches/0001-Add-plugin-support-to-bash.patch +++ b/src/bash/patches/0001-Add-plugin-support-to-bash.patch @@ -1,4 +1,4 @@ -From 8db363a7408976b808e9b2fc79549322381dc37a Mon Sep 17 00:00:00 2001 +From 2dea243108b0c59724cbf86ce73a4caf0c0c3f4a Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Thu, 9 Sep 2021 11:04:13 +0800 Subject: [PATCH] Add plugin support to bash. @@ -8,11 +8,11 @@ Subject: [PATCH] Add plugin support to bash. bash-5.0/config.h.in | 3 + bash-5.0/configure | 18 +- bash-5.0/configure.ac | 10 + - bash-5.0/execute_cmd.c | 15 ++ - bash-5.0/plugin.c | 421 +++++++++++++++++++++++++++++++++++++++++ + bash-5.0/execute_cmd.c | 16 ++ + bash-5.0/plugin.c | 427 +++++++++++++++++++++++++++++++++++++++++ bash-5.0/plugin.h | 75 ++++++++ bash-5.0/shell.c | 12 ++ - 8 files changed, 559 insertions(+), 9 deletions(-) + 8 files changed, 566 insertions(+), 9 deletions(-) create mode 100644 bash-5.0/plugin.c create mode 100644 bash-5.0/plugin.h @@ -211,7 +211,7 @@ index 52b4cdb..8070b94 100644 AC_DEFINE(ALIAS) fi diff --git a/bash-5.0/execute_cmd.c b/bash-5.0/execute_cmd.c -index 8b3c83a..8e1920b 100644 +index 8b3c83a..5485fd9 100644 --- a/bash-5.0/execute_cmd.c +++ b/bash-5.0/execute_cmd.c @@ -82,6 +82,10 @@ extern int errno; @@ -225,17 +225,18 @@ index 8b3c83a..8e1920b 100644 #include "builtins/common.h" #include "builtins/builtext.h" /* list of builtins */ -@@ -5458,6 +5462,17 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, +@@ -5458,6 +5462,18 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, leave it there, in the same format that the user used to type it in. */ args = strvec_from_word_list (words, 0, 0, (int *)NULL); + +#if defined (BASH_SHELL_EXECVE_PLUGIN) + result = invoke_plugin_on_shell_execve (current_user.user_name, command, args); -+ if (result) { ++ +#if defined (DEBUG) -+ itrace("invoke_plugin_on_shell_execve: failed invoke plugin with user:%s, command:%s", current_user.user_name, command); ++ itrace("invoke_plugin_on_shell_execve: failed invoke plugin with user:%s, command:%s, result: %d", current_user.user_name, command, result); +#endif ++ if (result) { + exit (EXECUTION_FAILURE); + } +#endif /* BASH_SHELL_EXECVE_PLUGIN */ @@ -245,10 +246,10 @@ index 8b3c83a..8e1920b 100644 else diff --git a/bash-5.0/plugin.c b/bash-5.0/plugin.c new file mode 100644 -index 0000000..2bfdf5a +index 0000000..32efe91 --- /dev/null +++ b/bash-5.0/plugin.c -@@ -0,0 +1,421 @@ +@@ -0,0 +1,427 @@ +/* plugin.c -- Bash plugin support. */ + +/* Copyright (C) 1987-2016 Free Software Foundation, Inc. @@ -398,7 +399,7 @@ index 0000000..2bfdf5a +PLUGIN_NODE *global_plugin_list = NULL; + +/* Load plugin by plugin path */ -+void ++int +append_plugin( + plugin_handle, + on_shell_execve, @@ -414,10 +415,8 @@ index 0000000..2bfdf5a + if (new_plugin_node == NULL) + { + /* When allocate memory failed, stop and return. */ -+#ifdef DEBUG -+ itrace("Plugin: failed to allocate memory for plugin node.\n"); -+#endif -+ return; ++ fprintf(stderr, "Plugin: failed to allocate memory for plugin node.\n"); ++ return PLUGIN_LOAD_FAILED; + } + + new_plugin_node->next = NULL; @@ -446,6 +445,8 @@ index 0000000..2bfdf5a +#ifdef DEBUG + itrace("Plugin: append new plugin node %p to %p\n", new_plugin_node, current_plugin_node); +#endif ++ ++ return PLUGIN_LOAD_SUCCESS; +} + + @@ -502,14 +503,20 @@ index 0000000..2bfdf5a + } + + /* Add plugin to plugin list */ -+ append_plugin(plugin_handle, ++ int plugin_load_result = append_plugin(plugin_handle, + plugin_on_shell_execve_handle, + plugin_init_handle, + plugin_uninit_handle); -+ ++ ++ if (plugin_load_result == PLUGIN_LOAD_SUCCESS) { +#ifdef DEBUG -+ itrace("Plugin: plugin %s loaded\n", plugin_path); ++ itrace("Plugin: plugin %s loaded\n", plugin_path); +#endif ++ } ++ else { ++ /* Output plugin load error message. */ ++ fprintf(stderr, "Plugin: plugin %s load failed, result: %d\n", plugin_path, plugin_load_result); ++ } +} + +/* Load plugin by config file */ @@ -660,10 +667,10 @@ index 0000000..2bfdf5a + if (absolute_program (cmd)) { + // find real path for relative path command + char resolved_path[PATH_MAX]; -+ -+ // real_path_buffer should not free here because we pass resolved_path as parameter. -+ char* real_path_buffer = realpath(cmd, resolved_path); -+ ++ ++ // real_path_buffer should not free here because we pass resolved_path as parameter. ++ char* real_path_buffer = realpath(cmd, resolved_path); ++ + return invoke_loaded_plugins(user, shell_level, resolved_path, argv); + } + else { From e85a16bacc61b45a10a6d50a354ea4fa90b33ce5 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Thu, 9 Sep 2021 14:13:39 +0800 Subject: [PATCH 15/24] Integrate UT. --- src/bash/Files/unittest/Makefile | 2 + src/bash/Files/unittest/bash_plugins.conf | 6 + src/bash/Files/unittest/mock_helper.c | 218 ++++++++++++++++++++++ src/bash/Files/unittest/mock_helper.h | 65 +++++++ src/bash/Files/unittest/plugin_test.c | 217 +++++++++++++++++++++ src/bash/Makefile | 7 + 6 files changed, 515 insertions(+) create mode 100644 src/bash/Files/unittest/bash_plugins.conf create mode 100644 src/bash/Files/unittest/mock_helper.c create mode 100644 src/bash/Files/unittest/mock_helper.h create mode 100644 src/bash/Files/unittest/plugin_test.c diff --git a/src/bash/Files/unittest/Makefile b/src/bash/Files/unittest/Makefile index 99f0b08a2eca..fee54deee07a 100644 --- a/src/bash/Files/unittest/Makefile +++ b/src/bash/Files/unittest/Makefile @@ -8,6 +8,8 @@ all: gcc mock_helper.c $(IFLAGS) $(CFLAGS) -o mock_helper.o gcc ../plugin.c $(IFLAGS) $(CFLAGS) $(MFLAG) -o plugin.o gcc plugin_test.o mock_helper.o plugin.o -o plugin_test -lc -lcunit + # run unit test, if UT failed, build will break + ./plugin_test clean: rm *.o diff --git a/src/bash/Files/unittest/bash_plugins.conf b/src/bash/Files/unittest/bash_plugins.conf new file mode 100644 index 000000000000..568de35efd37 --- /dev/null +++ b/src/bash/Files/unittest/bash_plugins.conf @@ -0,0 +1,6 @@ +# tacacs authorization plugin +plugin=/home/liuh/tacacs-bash-plugin/tacacs-authorization.so +plugin=/usr/lib/bash-plugins/another_test_plugin.so # test comments + + +# test line \ No newline at end of file diff --git a/src/bash/Files/unittest/mock_helper.c b/src/bash/Files/unittest/mock_helper.c new file mode 100644 index 000000000000..dfbf3a6444aa --- /dev/null +++ b/src/bash/Files/unittest/mock_helper.c @@ -0,0 +1,218 @@ +/* mock_helper.c -- mock helper for bash plugin UT. */ +#include +#include +#include +#include +#include +#include +#include "mock_helper.h" + +// define BASH_PLUGIN_UT_DEBUG to output UT debug message. +//#define BASH_PLUGIN_UT_DEBUG +#if defined (BASH_PLUGIN_UT_DEBUG) +# define debug_printf printf +#else +# define debug_printf +#endif + +/* itrace buffer */ +char mock_itrace_message_buffer[1024]; + +/* bash run command buffer */ +char mock_onshell_execve_command_buffer[1024]; + +/* plugin handles. */ +void* mock_plugin_handle = (void*)TEST_MOCK_PLUGIN_HANDLE; +void* mock_plugin_default_function_handle = (void*)0x2234; +void* mock_plugin_on_shell_execve_handle = (void*)0x3234; +char* mock_dlerror_failed = "MOCK error"; +char* mock_dlerror = NULL; + +/* define test scenarios for mock functions return different value by scenario. */ +int test_scenario; + +/* define test scenarios for different return value. */ +int plugin_init_status; + +/* define memory allocate counter. */ +int memory_allocate_count; + +/* Set test scenario for test*/ +void set_test_scenario(int scenario) +{ + test_scenario = scenario; +} + +/* Get test scenario for test*/ +int get_test_scenario() +{ + return test_scenario; +} + +/* Set plugin init status for test*/ +void set_plugin_init_status(int status) +{ + plugin_init_status = status; +} + +/* Get plugin init status for test*/ +int get_plugin_init_status() +{ + return plugin_init_status; +} + +/* Set memory allocate count for test*/ +void set_memory_allocate_count(int count) +{ + memory_allocate_count = count; +} + +/* Get memory allocate count for test*/ +int get_memory_allocate_count() +{ + return memory_allocate_count; +} + +/* MOCK plugin_init method*/ +int mock_plugin_init() +{ + set_plugin_init_status(PLUGIN_INITIALIZED); +} + +/* MOCK plugin_init method*/ +int mock_plugin_uninit() +{ + set_plugin_init_status(PLUGIN_NOT_INITIALIZE); +} + +/* MOCK on_shell_execve method*/ +int mock_on_shell_execve (char *user, int shell_level, char *cmd, char **argv) +{ + // set mock command data to buffer for UT. + memset(mock_onshell_execve_command_buffer, 0, sizeof(mock_onshell_execve_command_buffer)); + + snprintf(mock_onshell_execve_command_buffer, sizeof(mock_onshell_execve_command_buffer), "on_shell_execve: user: %s, level: %d, command: %s, argv: %p\n", user, shell_level, cmd, argv); + + debug_printf("MOCK: mock_on_shell_execve: %s\n", mock_onshell_execve_command_buffer); +} + +/* MOCK dlopen*/ +void *dlopen(const char *filename, int flags) +{ + debug_printf("MOCK: dlopen: %s\n", filename); + if (TEST_SCEANRIO_PLUGIN_NOT_EXIT == test_scenario) + { + // return null when plugin not exist + mock_dlerror = mock_dlerror_failed; + return NULL; + } + + // all other case return mock handle + mock_dlerror = NULL; + return mock_plugin_handle; +} + +/* MOCK dlclose*/ +int dlclose(void *handle) +{ + debug_printf("MOCK: dlclose: %p\n", handle); + // check if the close handle match the opened handle + CU_ASSERT_EQUAL(handle, mock_plugin_handle); +} + +/* MOCK dlsym*/ +void *dlsym(void *restrict handle, const char *restrict symbol) +{ + debug_printf("MOCK: dlsym: %p, %s\n", handle, symbol); + mock_dlerror = NULL; + switch (test_scenario) + { + case TEST_SCEANRIO_PLUGIN_EXECVE_NOT_EXIT: + if (strcmp(symbol, "on_shell_execve") == 0) + { + mock_dlerror = mock_dlerror_failed; + return NULL; + } + + case TEST_SCEANRIO_PLUGIN_UNINIT_NOT_EXIT: + if (strcmp(symbol, "plugin_uninit") == 0) + { + mock_dlerror = mock_dlerror_failed; + return NULL; + } + + case TEST_SCEANRIO_PLUGIN_INIT_NOT_EXIT: + if (strcmp(symbol, "plugin_init") == 0) + { + mock_dlerror = mock_dlerror_failed; + return NULL; + } + + case TEST_SCEANRIO_PLUGIN_INIT_SUCCESS: + if (strcmp(symbol, "plugin_init") == 0) + { + // return mock method handle so plugin framework will call it to initialize + return mock_plugin_init; + } + else if (strcmp(symbol, "plugin_uninit") == 0) + { + // return mock method handle so plugin framework will call it to initialize + return mock_plugin_uninit; + } + else if (strcmp(symbol, "on_shell_execve") == 0) + { + // return mock method handle so plugin framework will call it to initialize + return mock_on_shell_execve; + } + } + + return mock_plugin_default_function_handle; +} + +/* MOCK dlerror*/ +char *dlerror(void) +{ + return mock_dlerror; +} + +/* MOCK get_string_value*/ +char *get_string_value(const char * str) +{ + return "1"; +} + +/* MOCK absolute_program*/ +int absolute_program (const char * str) +{ + return 0; +} + +/* MOCK itrace*/ +void itrace (const char * format, ...) +{ + // set mock message data to buffer for UT. + memset(mock_itrace_message_buffer, 0, sizeof(mock_itrace_message_buffer)); + + va_list args; + va_start(args, format); + // save message to buffer to UT check later + vsnprintf(mock_itrace_message_buffer, sizeof(mock_itrace_message_buffer), format, args); + va_end(args); + debug_printf("MOCK: itrace: %s\n", mock_itrace_message_buffer); +} + +/* MOCK malloc method*/ +void* mock_malloc (size_t size) +{ + memory_allocate_count++; + debug_printf("MOCK: malloc memory count: %d\n", memory_allocate_count); + return malloc(size); +} + +/* MOCK free method*/ +void mock_free (void* ptr) +{ + memory_allocate_count--; + debug_printf("MOCK: free memory count: %d\n", memory_allocate_count); + free(ptr); +} \ No newline at end of file diff --git a/src/bash/Files/unittest/mock_helper.h b/src/bash/Files/unittest/mock_helper.h new file mode 100644 index 000000000000..1fcfeb39be9b --- /dev/null +++ b/src/bash/Files/unittest/mock_helper.h @@ -0,0 +1,65 @@ +/* plugin.h - functions from plugin.c. */ + +/* Copyright (C) 1993-2015 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bash. If not, see . +*/ + +#if !defined (_MOCK_HELPER_H_) +#define _MOCK_HELPER_H_ + +#include "plugin.h" + +#define TEST_MOCK_PLUGIN_HANDLE 0x1234 + +#define TEST_SCEANRIO_PLUGIN_NOT_EXIT 1 +#define TEST_SCEANRIO_PLUGIN_EXECVE_NOT_EXIT 2 +#define TEST_SCEANRIO_PLUGIN_UNINIT_NOT_EXIT 3 +#define TEST_SCEANRIO_PLUGIN_INIT_NOT_EXIT 4 +#define TEST_SCEANRIO_PLUGIN_INIT_SUCCESS 5 + +#define PLUGIN_NOT_INITIALIZE -1 +#define PLUGIN_INITIALIZED 1 + +/* The global plugin list */ +extern PLUGIN_NODE *global_plugin_list; + +/* itrace buffer */ +extern char mock_itrace_message_buffer[1024]; + +/* bash run command buffer */ +extern char mock_onshell_execve_command_buffer[1024]; + +/* Set test scenario for test*/ +void set_test_scenario(int scenario); + +/* Get test scenario for test*/ +int get_test_scenario(); + +/* Set plugin init status for test*/ +void set_plugin_init_status(int status); + +/* Get plugin init status for test*/ +int get_plugin_init_status(); + +/* Set memory allocate count for test*/ +void set_memory_allocate_count(int count); + +/* Get memory allocate count for test*/ +int get_memory_allocate_count(); + + +#endif /* _MOCK_HELPER_H_ */ \ No newline at end of file diff --git a/src/bash/Files/unittest/plugin_test.c b/src/bash/Files/unittest/plugin_test.c new file mode 100644 index 000000000000..9382e0b1796a --- /dev/null +++ b/src/bash/Files/unittest/plugin_test.c @@ -0,0 +1,217 @@ +#include +#include +#include +#include +#include "plugin.h" +#include "mock_helper.h" + +int clean_up() { + return 0; +} + +int start_up() { + return 0; +} + +/* Test plugin not exist scenario */ +void testcase_try_load_plugin_by_path_not_exist() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_NOT_EXIT); + + try_load_plugin_by_path("./testplugin.so"); + + CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't load plugin ./testplugin.so: MOCK error\n"); +} + +/* Test plugin exist but not support shell_execve scenario */ +void testcase_try_load_plugin_by_path_execve_not_exist() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_EXECVE_NOT_EXIT); + + try_load_plugin_by_path("./testplugin.so"); + + CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't find on_shell_execve function ./testplugin.so: MOCK error\n"); +} + +/* Test plugin exist but not support plugin_uninit scenario */ +void testcase_try_load_plugin_by_path_plugin_uninit_not_exist() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_UNINIT_NOT_EXIT); + + try_load_plugin_by_path("./testplugin.so"); + + CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't find plugin_uninit function ./testplugin.so: MOCK error\n"); +} + +/* Test plugin exist but not support plugin_init scenario */ +void testcase_try_load_plugin_by_path_plugin_init_not_exist() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_NOT_EXIT); + + try_load_plugin_by_path("./testplugin.so"); + + CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't find plugin_init function ./testplugin.so: MOCK error\n"); +} + +/* Test plugin exist but not support plugin_init scenario */ +void testcase_try_load_plugin_by_path_plugin_init_success() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_SUCCESS); + set_memory_allocate_count(0); + set_plugin_init_status(PLUGIN_NOT_INITIALIZE); + + try_load_plugin_by_path("./testplugin.so"); + + // check plugin init success + CU_ASSERT_EQUAL(get_plugin_init_status(), PLUGIN_INITIALIZED); + + // check API success + CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: plugin ./testplugin.so loaded\n"); + + // check global plugin list not empty and contains correct pluginglobal_plugin_list + CU_ASSERT_NOT_EQUAL(global_plugin_list, NULL); + CU_ASSERT_EQUAL(global_plugin_list->plugin_handle, TEST_MOCK_PLUGIN_HANDLE); + + // release all loaded plugins + free_loaded_plugins(); + + // check if memory fully released + CU_ASSERT_EQUAL(global_plugin_list, NULL); + CU_ASSERT_EQUAL(get_memory_allocate_count(), 0); +} + +/* Test free loaded plugins */ +void testcase_release_loaded_plugin() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_SUCCESS); + set_memory_allocate_count(0); + try_load_plugin_by_path("./testplugin.so"); + + // check memory allocated + CU_ASSERT_NOT_EQUAL(get_memory_allocate_count(), 0); + + // check plugin init success + CU_ASSERT_EQUAL(get_plugin_init_status(), PLUGIN_INITIALIZED); + + // release all loaded plugins + free_loaded_plugins(); + + // check if memory fully released + CU_ASSERT_EQUAL(global_plugin_list, NULL); + CU_ASSERT_EQUAL(get_memory_allocate_count(), 0); +} + +/* Test load plugin by config */ +void testcase_load_plugin_by_config() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_SUCCESS); + set_memory_allocate_count(0); + load_plugin_by_config("./bash_plugins.conf"); + + // check memory allocated + CU_ASSERT_NOT_EQUAL(get_memory_allocate_count(), 0); + + // check plugin init success + CU_ASSERT_EQUAL(get_plugin_init_status(), PLUGIN_INITIALIZED); + + // check target plugin in config file loaded + CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: plugin /usr/lib/bash-plugins/another_test_plugin.so loaded\n"); + + // check there are 2 plugins loaded + CU_ASSERT_EQUAL(get_memory_allocate_count(), 2); + + // release all loaded plugins + free_loaded_plugins(); + + // check if memory fully released + CU_ASSERT_EQUAL(global_plugin_list, NULL); + printf("Count %d\n", get_memory_allocate_count()); + CU_ASSERT_EQUAL(get_memory_allocate_count(), 0); +} + +/* Test invoke on_shell_execve plugin method */ +void testcase_invoke_plugin_on_shell_execve() { + set_test_scenario(TEST_SCEANRIO_PLUGIN_INIT_SUCCESS); + set_memory_allocate_count(0); + load_plugin_by_config("./bash_plugins.conf"); + + // invoke plugin method + char** pargv = (char**)0x5234; + invoke_plugin_on_shell_execve("testuser", "testcommand", pargv); + printf(mock_onshell_execve_command_buffer); + CU_ASSERT_STRING_EQUAL(mock_onshell_execve_command_buffer, "on_shell_execve: user: testuser, level: 1, command: testcommand, argv: 0x5234\n"); + + // release all loaded plugins + free_loaded_plugins(); + + // check if memory fully released + CU_ASSERT_EQUAL(global_plugin_list, NULL); + printf("Count %d\n", get_memory_allocate_count()); + CU_ASSERT_EQUAL(get_memory_allocate_count(), 0); +} + +int main(void) { + if (CUE_SUCCESS != CU_initialize_registry()) { + return CU_get_error(); + } + + CU_pSuite ste = CU_add_suite("plugin_test", start_up, clean_up); + if (NULL == ste) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (CU_get_error() != CUE_SUCCESS) { + fprintf(stderr, "Error creating suite: (%d)%s\n", CU_get_error(), CU_get_error_msg()); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_not_exist()...\n", testcase_try_load_plugin_by_path_not_exist)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_execve_not_exist()...\n", testcase_try_load_plugin_by_path_execve_not_exist)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_plugin_uninit_not_exist()...\n", testcase_try_load_plugin_by_path_plugin_uninit_not_exist)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_plugin_init_not_exist()...\n", testcase_try_load_plugin_by_path_plugin_init_not_exist)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_try_load_plugin_by_path_plugin_init_success()...\n", testcase_try_load_plugin_by_path_plugin_init_success)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_release_loaded_plugin()...\n", testcase_release_loaded_plugin)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_load_plugin_by_config()...\n", testcase_load_plugin_by_config)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (!CU_add_test(ste, "Test testcase_invoke_plugin_on_shell_execve()...\n", testcase_invoke_plugin_on_shell_execve)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (CU_get_error() != CUE_SUCCESS) { + fprintf(stderr, "Error adding test: (%d)%s\n", CU_get_error(), CU_get_error_msg()); + } + + // run all test + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_ErrorCode run_errors = CU_basic_run_suite(ste); + if (run_errors != CUE_SUCCESS) { + fprintf(stderr, "Error running tests: (%d)%s\n", run_errors, CU_get_error_msg()); + } + + CU_basic_show_failures(CU_get_failure_list()); + + // use failed UT count as return value + return CU_get_number_of_failure_records(); +} \ No newline at end of file diff --git a/src/bash/Makefile b/src/bash/Makefile index 7c0f5c72d4b7..307cb8ef4779 100644 --- a/src/bash/Makefile +++ b/src/bash/Makefile @@ -13,8 +13,15 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : quilt push -a pushd bash-$(BASH_VERSION_MAJOR) + # copy UT and source code. cp -a ../Files/. ./ + + # run UT before build package + pushd unittest + make + popd + # build package DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) From 112a6568c4dfd159805e2882c14452397ab5dcd6 Mon Sep 17 00:00:00 2001 From: liuh Date: Thu, 9 Sep 2021 20:02:53 +0800 Subject: [PATCH 16/24] Fix UT build issue. --- src/bash/Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bash/Makefile b/src/bash/Makefile index 307cb8ef4779..9dfdb37b52d7 100644 --- a/src/bash/Makefile +++ b/src/bash/Makefile @@ -14,17 +14,17 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : pushd bash-$(BASH_VERSION_MAJOR) - # copy UT and source code. + # build package + DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) + + # copy UT code. cp -a ../Files/. ./ - # run UT before build package + # run UT after build package because we need config.h pushd unittest make popd - # build package - DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) - popd mv $* $(DEST)/ From 84e57ccd140b02b7167e8b78ad7ee5a200785d4f Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Fri, 10 Sep 2021 09:29:43 +0800 Subject: [PATCH 17/24] Fix build issue. --- .../patches/0001-Add-plugin-support-to-bash.patch | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/bash/patches/0001-Add-plugin-support-to-bash.patch b/src/bash/patches/0001-Add-plugin-support-to-bash.patch index b22be978535a..c50981c026cd 100644 --- a/src/bash/patches/0001-Add-plugin-support-to-bash.patch +++ b/src/bash/patches/0001-Add-plugin-support-to-bash.patch @@ -1,4 +1,4 @@ -From 2dea243108b0c59724cbf86ce73a4caf0c0c3f4a Mon Sep 17 00:00:00 2001 +From b358f583f2548dfb387a031e102742138dde321f Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Thu, 9 Sep 2021 11:04:13 +0800 Subject: [PATCH] Add plugin support to bash. @@ -10,9 +10,9 @@ Subject: [PATCH] Add plugin support to bash. bash-5.0/configure.ac | 10 + bash-5.0/execute_cmd.c | 16 ++ bash-5.0/plugin.c | 427 +++++++++++++++++++++++++++++++++++++++++ - bash-5.0/plugin.h | 75 ++++++++ + bash-5.0/plugin.h | 79 ++++++++ bash-5.0/shell.c | 12 ++ - 8 files changed, 566 insertions(+), 9 deletions(-) + 8 files changed, 570 insertions(+), 9 deletions(-) create mode 100644 bash-5.0/plugin.c create mode 100644 bash-5.0/plugin.h @@ -679,10 +679,10 @@ index 0000000..32efe91 +} diff --git a/bash-5.0/plugin.h b/bash-5.0/plugin.h new file mode 100644 -index 0000000..5aa5e67 +index 0000000..116b2c5 --- /dev/null +++ b/bash-5.0/plugin.h -@@ -0,0 +1,75 @@ +@@ -0,0 +1,79 @@ +/* plugin.h - functions from plugin.c. */ + +/* Copyright (C) 1993-2015 Free Software Foundation, Inc. @@ -711,6 +711,10 @@ index 0000000..5aa5e67 +/* System-wide bash plugin configuration. */ +#define SYS_BASH_PLUGIN "/etc/bash.plugin" + ++/* Plugin load result. */ ++#define PLUGIN_LOAD_SUCCESS 0 ++#define PLUGIN_LOAD_FAILED 1 ++ +typedef enum { T_COMMAND } plugin_type_t; + +/* Bash plugin config. */ From 9fa560cbce1c07baa6f23b6e2171c31acceb696e Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Fri, 10 Sep 2021 14:21:27 +0800 Subject: [PATCH 18/24] Improve code. --- .../0001-Add-plugin-support-to-bash.patch | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/bash/patches/0001-Add-plugin-support-to-bash.patch b/src/bash/patches/0001-Add-plugin-support-to-bash.patch index c50981c026cd..d37334925e8e 100644 --- a/src/bash/patches/0001-Add-plugin-support-to-bash.patch +++ b/src/bash/patches/0001-Add-plugin-support-to-bash.patch @@ -1,4 +1,4 @@ -From b358f583f2548dfb387a031e102742138dde321f Mon Sep 17 00:00:00 2001 +From 0390c526253b627e3680eca2faf6bbfcf3f75525 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Thu, 9 Sep 2021 11:04:13 +0800 Subject: [PATCH] Add plugin support to bash. @@ -9,10 +9,10 @@ Subject: [PATCH] Add plugin support to bash. bash-5.0/configure | 18 +- bash-5.0/configure.ac | 10 + bash-5.0/execute_cmd.c | 16 ++ - bash-5.0/plugin.c | 427 +++++++++++++++++++++++++++++++++++++++++ + bash-5.0/plugin.c | 428 +++++++++++++++++++++++++++++++++++++++++ bash-5.0/plugin.h | 79 ++++++++ bash-5.0/shell.c | 12 ++ - 8 files changed, 570 insertions(+), 9 deletions(-) + 8 files changed, 571 insertions(+), 9 deletions(-) create mode 100644 bash-5.0/plugin.c create mode 100644 bash-5.0/plugin.h @@ -246,10 +246,10 @@ index 8b3c83a..5485fd9 100644 else diff --git a/bash-5.0/plugin.c b/bash-5.0/plugin.c new file mode 100644 -index 0000000..32efe91 +index 0000000..df72830 --- /dev/null +++ b/bash-5.0/plugin.c -@@ -0,0 +1,427 @@ +@@ -0,0 +1,428 @@ +/* plugin.c -- Bash plugin support. */ + +/* Copyright (C) 1987-2016 Free Software Foundation, Inc. @@ -295,6 +295,7 @@ index 0000000..32efe91 +#include "filecntl.h" +#include "posixstat.h" +#include ++#include +#if defined (HAVE_SYS_PARAM_H) +# include +#endif @@ -414,8 +415,8 @@ index 0000000..32efe91 + PLUGIN_NODE *new_plugin_node = (PLUGIN_NODE*)malloc(sizeof(PLUGIN_NODE)); + if (new_plugin_node == NULL) + { -+ /* When allocate memory failed, stop and return. */ -+ fprintf(stderr, "Plugin: failed to allocate memory for plugin node.\n"); ++ /* When allocate memory failed, stop and return. also output log to both syslog and stderr with LOG_PERROR*/ ++ syslog(LOG_PERROR, "Plugin: failed to allocate memory for plugin node.\n"); + return PLUGIN_LOAD_FAILED; + } + @@ -514,8 +515,8 @@ index 0000000..32efe91 +#endif + } + else { -+ /* Output plugin load error message. */ -+ fprintf(stderr, "Plugin: plugin %s load failed, result: %d\n", plugin_path, plugin_load_result); ++ /* Output plugin load error message, also output log to both syslog and stderr with LOG_PERROR*/ ++ syslog(LOG_PERROR,"Plugin: plugin %s load failed, result: %d\n", plugin_path, plugin_load_result); + } +} + From 989c52c2763ddb0647270a622df0eb2d8d9cc13c Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 14 Sep 2021 04:59:17 +0000 Subject: [PATCH 19/24] Fix CUnit missing issue --- sonic-slave-bullseye/Dockerfile.j2 | 2 ++ sonic-slave-buster/Dockerfile.j2 | 2 ++ sonic-slave-jessie/Dockerfile.j2 | 2 ++ sonic-slave-stretch/Dockerfile.j2 | 2 ++ src/bash/Files/unittest/plugin_test.c | 4 ++-- 5 files changed, 10 insertions(+), 2 deletions(-) diff --git a/sonic-slave-bullseye/Dockerfile.j2 b/sonic-slave-bullseye/Dockerfile.j2 index 412aac07b1f9..8a6e68b0546a 100644 --- a/sonic-slave-bullseye/Dockerfile.j2 +++ b/sonic-slave-bullseye/Dockerfile.j2 @@ -254,6 +254,8 @@ RUN apt-get update && apt-get install -y \ locales \ time \ man2html-base \ + libcunit1 \ + libcunit1-dev \ # For initramfs shellcheck \ bash-completion \ diff --git a/sonic-slave-buster/Dockerfile.j2 b/sonic-slave-buster/Dockerfile.j2 index 1b3173373c10..8033f8d0a7c9 100644 --- a/sonic-slave-buster/Dockerfile.j2 +++ b/sonic-slave-buster/Dockerfile.j2 @@ -262,6 +262,8 @@ RUN apt-get update && apt-get install -y \ locales \ time \ man2html-base \ + libcunit1 \ + libcunit1-dev \ # For initramfs shellcheck \ bash-completion \ diff --git a/sonic-slave-jessie/Dockerfile.j2 b/sonic-slave-jessie/Dockerfile.j2 index b9375e65c76e..b23f06880344 100644 --- a/sonic-slave-jessie/Dockerfile.j2 +++ b/sonic-slave-jessie/Dockerfile.j2 @@ -235,6 +235,8 @@ RUN apt-get update && apt-get install -y \ locales \ time \ man2html-base \ + libcunit1 \ + libcunit1-dev \ # For initramfs bash-completion \ {% if CONFIGURED_ARCH == "amd64" -%} diff --git a/sonic-slave-stretch/Dockerfile.j2 b/sonic-slave-stretch/Dockerfile.j2 index 0505d12af6e6..ed37d506cf41 100644 --- a/sonic-slave-stretch/Dockerfile.j2 +++ b/sonic-slave-stretch/Dockerfile.j2 @@ -258,6 +258,8 @@ RUN apt-get update && apt-get install -y \ locales \ time \ man2html-base \ + libcunit1 \ + libcunit1-dev \ # For initramfs bash-completion \ {%- if CONFIGURED_ARCH == "amd64" %} diff --git a/src/bash/Files/unittest/plugin_test.c b/src/bash/Files/unittest/plugin_test.c index 9382e0b1796a..cca839c0cdec 100644 --- a/src/bash/Files/unittest/plugin_test.c +++ b/src/bash/Files/unittest/plugin_test.c @@ -19,7 +19,7 @@ void testcase_try_load_plugin_by_path_not_exist() { try_load_plugin_by_path("./testplugin.so"); - CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't load plugin ./testplugin.so: MOCK error\n"); + CU_ASSERT_STRING_NOT_EQUAL(mock_itrace_message_buffer, "Plugin: can't load plugin ./testplugin.so: MOCK error\n"); } /* Test plugin exist but not support shell_execve scenario */ @@ -214,4 +214,4 @@ int main(void) { // use failed UT count as return value return CU_get_number_of_failure_records(); -} \ No newline at end of file +} From 614c2ce85b327d649c352e8670b11eb7b57df549 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 14 Sep 2021 05:02:35 +0000 Subject: [PATCH 20/24] Fix CUnit missing issue --- src/bash/Files/unittest/plugin_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bash/Files/unittest/plugin_test.c b/src/bash/Files/unittest/plugin_test.c index cca839c0cdec..83439f93a03f 100644 --- a/src/bash/Files/unittest/plugin_test.c +++ b/src/bash/Files/unittest/plugin_test.c @@ -19,7 +19,7 @@ void testcase_try_load_plugin_by_path_not_exist() { try_load_plugin_by_path("./testplugin.so"); - CU_ASSERT_STRING_NOT_EQUAL(mock_itrace_message_buffer, "Plugin: can't load plugin ./testplugin.so: MOCK error\n"); + CU_ASSERT_STRING_EQUAL(mock_itrace_message_buffer, "Plugin: can't load plugin ./testplugin.so: MOCK error\n"); } /* Test plugin exist but not support shell_execve scenario */ From c8a7734363318ddf976a655091e636016456214d Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Tue, 14 Sep 2021 16:54:40 +0800 Subject: [PATCH 21/24] Fix UT build issue. --- src/bash/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bash/Makefile b/src/bash/Makefile index 9dfdb37b52d7..b3a8523406fe 100644 --- a/src/bash/Makefile +++ b/src/bash/Makefile @@ -20,7 +20,10 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : # copy UT code. cp -a ../Files/. ./ - # run UT after build package because we need config.h + # generate config.h which need by UT + ./configure + + # run UT after config.h ready. pushd unittest make popd From d4d1846c96b656537a957bda64f163da693dba29 Mon Sep 17 00:00:00 2001 From: liuh Date: Wed, 15 Sep 2021 14:28:33 +0800 Subject: [PATCH 22/24] Fix UT build break issue. --- src/bash/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bash/Makefile b/src/bash/Makefile index b3a8523406fe..fbc18b2362df 100644 --- a/src/bash/Makefile +++ b/src/bash/Makefile @@ -23,6 +23,9 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : # generate config.h which need by UT ./configure + # generate 'pathnames.h' by make bash again, which is needed by UT. + make + # run UT after config.h ready. pushd unittest make From fa977010e20c8d83996886922a5aefb4a63b781a Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Thu, 16 Sep 2021 11:16:45 +0800 Subject: [PATCH 23/24] Improve code by PR comments. --- src/bash/Files/unittest/Makefile | 2 ++ src/bash/Makefile | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bash/Files/unittest/Makefile b/src/bash/Files/unittest/Makefile index fee54deee07a..8eec2b07ab45 100644 --- a/src/bash/Files/unittest/Makefile +++ b/src/bash/Files/unittest/Makefile @@ -8,6 +8,8 @@ all: gcc mock_helper.c $(IFLAGS) $(CFLAGS) -o mock_helper.o gcc ../plugin.c $(IFLAGS) $(CFLAGS) $(MFLAG) -o plugin.o gcc plugin_test.o mock_helper.o plugin.o -o plugin_test -lc -lcunit + +test: # run unit test, if UT failed, build will break ./plugin_test diff --git a/src/bash/Makefile b/src/bash/Makefile index b3a8523406fe..c5abaf77b124 100644 --- a/src/bash/Makefile +++ b/src/bash/Makefile @@ -24,9 +24,7 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : ./configure # run UT after config.h ready. - pushd unittest - make - popd + make -C unittest && make test -C unittest popd From ec852b42127c273c34335487c75b684c8d7e5b64 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Fri, 8 Oct 2021 16:41:12 +0800 Subject: [PATCH 24/24] Change to use 5.1-2 for debian-11 bullseye. --- rules/bash.mk | 10 +- .../0001-Add-plugin-support-to-bash.patch | 128 +++++++++--------- 2 files changed, 69 insertions(+), 69 deletions(-) diff --git a/rules/bash.mk b/rules/bash.mk index f881af664507..48c089c49e0d 100644 --- a/rules/bash.mk +++ b/rules/bash.mk @@ -1,12 +1,12 @@ # bash package # -# Created to patch plugin support in the bash-package included in Debian-10 (Buster) +# Created to patch plugin support in the bash-package included in Debian-11 (Bullseye) # release. -# Bash major release-number corresponding to Debian-10 (Buster) -BASH_VERSION_MAJOR = 5.0 -# Bash complete release-number. This image contains all 5.0 fixes up to patch '4'. -BASH_VERSION_FULL = $(BASH_VERSION_MAJOR)-4 +# Bash major release-number corresponding to Debian-11 (Bullseye) +BASH_VERSION_MAJOR = 5.1 +# Bash complete release-number. This image contains all 5.1 fixes up to patch '2'. +BASH_VERSION_FULL = $(BASH_VERSION_MAJOR)-2 export BASH_VERSION_MAJOR BASH_VERSION_FULL diff --git a/src/bash/patches/0001-Add-plugin-support-to-bash.patch b/src/bash/patches/0001-Add-plugin-support-to-bash.patch index d37334925e8e..bec53ba8b5df 100644 --- a/src/bash/patches/0001-Add-plugin-support-to-bash.patch +++ b/src/bash/patches/0001-Add-plugin-support-to-bash.patch @@ -1,26 +1,26 @@ -From 0390c526253b627e3680eca2faf6bbfcf3f75525 Mon Sep 17 00:00:00 2001 +From 79b3c4f7e8589afae4b048d662a56b055436e9ab Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> -Date: Thu, 9 Sep 2021 11:04:13 +0800 +Date: Fri, 8 Oct 2021 16:36:34 +0800 Subject: [PATCH] Add plugin support to bash. --- - bash-5.0/Makefile.in | 14 +- - bash-5.0/config.h.in | 3 + - bash-5.0/configure | 18 +- - bash-5.0/configure.ac | 10 + - bash-5.0/execute_cmd.c | 16 ++ - bash-5.0/plugin.c | 428 +++++++++++++++++++++++++++++++++++++++++ - bash-5.0/plugin.h | 79 ++++++++ - bash-5.0/shell.c | 12 ++ + bash-5.1/Makefile.in | 14 +- + bash-5.1/config.h.in | 3 + + bash-5.1/configure | 18 +- + bash-5.1/configure.ac | 10 + + bash-5.1/execute_cmd.c | 16 ++ + bash-5.1/plugin.c | 428 +++++++++++++++++++++++++++++++++++++++++ + bash-5.1/plugin.h | 79 ++++++++ + bash-5.1/shell.c | 12 ++ 8 files changed, 571 insertions(+), 9 deletions(-) - create mode 100644 bash-5.0/plugin.c - create mode 100644 bash-5.0/plugin.h + create mode 100644 bash-5.1/plugin.c + create mode 100644 bash-5.1/plugin.h -diff --git a/bash-5.0/Makefile.in b/bash-5.0/Makefile.in -index 5fcb44b..9e4e4c3 100644 ---- a/bash-5.0/Makefile.in -+++ b/bash-5.0/Makefile.in -@@ -379,6 +379,9 @@ LTLIBINTL = @LTLIBINTL@ +diff --git a/bash-5.1/Makefile.in b/bash-5.1/Makefile.in +index 3e3a5d4..16169cd 100644 +--- a/bash-5.1/Makefile.in ++++ b/bash-5.1/Makefile.in +@@ -380,6 +380,9 @@ LTLIBINTL = @LTLIBINTL@ INTLLIBS = @INTLLIBS@ INTLOBJS = @INTLOBJS@ @@ -30,7 +30,7 @@ index 5fcb44b..9e4e4c3 100644 # Our malloc. MALLOC_TARGET = @MALLOC_TARGET@ -@@ -420,7 +423,7 @@ BASHINCFILES = $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/ansi_stdlib.h \ +@@ -421,7 +424,7 @@ BASHINCFILES = $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/ansi_stdlib.h \ $(BASHINCDIR)/ocache.h LIBRARIES = $(GLOB_LIB) $(SHLIB_LIB) $(READLINE_LIB) $(HISTORY_LIB) $(TERMCAP_LIB) \ @@ -39,7 +39,7 @@ index 5fcb44b..9e4e4c3 100644 LIBDEP = $(GLOB_DEP) $(SHLIB_DEP) $(INTL_DEP) $(READLINE_DEP) $(HISTORY_DEP) $(TERMCAP_DEP) \ $(TILDE_DEP) $(MALLOC_DEP) -@@ -440,7 +443,7 @@ CSOURCES = shell.c eval.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \ +@@ -441,7 +444,7 @@ CSOURCES = shell.c eval.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \ input.c bashhist.c array.c arrayfunc.c assoc.c sig.c pathexp.c \ unwind_prot.c siglist.c bashline.c bracecomp.c error.c \ list.c stringlib.c locale.c findcmd.c redir.c \ @@ -48,7 +48,7 @@ index 5fcb44b..9e4e4c3 100644 HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ general.h variables.h config.h $(ALLOC_HEADERS) alias.h \ -@@ -448,7 +451,7 @@ HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ +@@ -449,7 +452,7 @@ HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \ command.h input.h error.h bashansi.h dispose_cmd.h make_cmd.h \ subst.h externs.h siglist.h bashhist.h bashline.h bashtypes.h \ array.h arrayfunc.h sig.h mailcheck.h bashintl.h bashjmp.h \ @@ -57,7 +57,7 @@ index 5fcb44b..9e4e4c3 100644 $(BASHINCFILES) SOURCES = $(CSOURCES) $(HSOURCES) $(BUILTIN_DEFS) -@@ -481,7 +484,7 @@ OBJECTS = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \ +@@ -482,7 +485,7 @@ OBJECTS = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \ trap.o input.o unwind_prot.o pathexp.o sig.o test.o version.o \ alias.o array.o arrayfunc.o assoc.o braces.o bracecomp.o bashhist.o \ bashline.o $(SIGLIST_O) list.o stringlib.o locale.o findcmd.o redir.o \ @@ -66,27 +66,27 @@ index 5fcb44b..9e4e4c3 100644 # Where the source code of the shell builtins resides. BUILTIN_SRCDIR=$(srcdir)/builtins -@@ -1015,7 +1018,7 @@ eval.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h - eval.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h +@@ -1039,7 +1042,7 @@ eval.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h eval.o: input.h execute_cmd.h + eval.o: bashhist.h assoc.h ${BASHINCDIR}/ocache.h ${BASHINCDIR}/chartypes.h execute_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h -execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h +execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h plugin.h execute_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h execute_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h execute_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h parser.h -@@ -1024,6 +1027,7 @@ execute_cmd.o: execute_cmd.h findcmd.h redir.h trap.h test.h pathexp.h - execute_cmd.o: $(DEFSRC)/common.h ${DEFDIR}/builtext.h ${GLOB_LIBSRC}/strmatch.h - execute_cmd.o: ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/chartypes.h +@@ -1050,6 +1053,7 @@ execute_cmd.o: ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/chartypes.h execute_cmd.o: $(DEFSRC)/getopt.h + execute_cmd.o: bashhist.h input.h ${GRAM_H} assoc.h hashcmd.h alias.h + execute_cmd.o: ${BASHINCDIR}/ocache.h ${BASHINCDIR}/posixwait.h +plugin.o: plugin.h expr.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h expr.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h expr.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h -diff --git a/bash-5.0/config.h.in b/bash-5.0/config.h.in -index 8554aec..7f17024 100644 ---- a/bash-5.0/config.h.in -+++ b/bash-5.0/config.h.in +diff --git a/bash-5.1/config.h.in b/bash-5.1/config.h.in +index ab316d4..ab5634f 100644 +--- a/bash-5.1/config.h.in ++++ b/bash-5.1/config.h.in @@ -38,6 +38,9 @@ BSD-like job control. */ #undef JOB_CONTROL @@ -97,11 +97,11 @@ index 8554aec..7f17024 100644 /* Define ALIAS if you want the alias features. */ #undef ALIAS -diff --git a/bash-5.0/configure b/bash-5.0/configure -index 2f62662..cae212f 100644 ---- a/bash-5.0/configure -+++ b/bash-5.0/configure -@@ -630,6 +630,7 @@ LOCAL_DEFS +diff --git a/bash-5.1/configure b/bash-5.1/configure +index 0f1d3ed..c462d55 100644 +--- a/bash-5.1/configure ++++ b/bash-5.1/configure +@@ -632,6 +632,7 @@ LOCAL_DEFS LOCAL_LDFLAGS LOCAL_CFLAGS LOCAL_LIBS @@ -109,7 +109,7 @@ index 2f62662..cae212f 100644 MALLOC_DEBUG DEBUG RELSTATUS -@@ -827,6 +828,7 @@ enable_single_help_strings +@@ -858,6 +859,7 @@ enable_single_help_strings enable_strict_posix_default enable_usg_echo_default enable_xpg_echo_default @@ -117,7 +117,7 @@ index 2f62662..cae212f 100644 enable_mem_scramble enable_profiling enable_static_link -@@ -1535,6 +1537,7 @@ Optional Features: +@@ -1568,6 +1570,7 @@ Optional Features: --enable-xpg-echo-default make the echo builtin expand escape sequences by default @@ -125,7 +125,7 @@ index 2f62662..cae212f 100644 --enable-mem-scramble scramble memory on calls to malloc and free --enable-profiling allow profiling with gprof --enable-static-link link bash statically, for use as a root shell -@@ -2989,6 +2992,7 @@ opt_dircomplete_expand_default=no +@@ -3027,6 +3030,7 @@ opt_dircomplete_expand_default=no opt_globascii_default=yes opt_function_import=yes opt_dev_fd_stat_broken=no @@ -133,7 +133,7 @@ index 2f62662..cae212f 100644 opt_static_link=no opt_profiling=no -@@ -3010,6 +3014,7 @@ if test $opt_minimal_config = yes; then +@@ -3048,6 +3052,7 @@ if test $opt_minimal_config = yes; then opt_multibyte=yes opt_cond_regexp=no opt_coproc=no opt_casemod_attrs=no opt_casemod_expansions=no opt_extglob_default=no opt_globascii_default=yes @@ -141,7 +141,7 @@ index 2f62662..cae212f 100644 fi # Check whether --enable-alias was given. -@@ -3197,6 +3202,10 @@ if test "${enable_xpg_echo_default+set}" = set; then : +@@ -3235,6 +3240,10 @@ if test "${enable_xpg_echo_default+set}" = set; then : enableval=$enable_xpg_echo_default; opt_xpg_echo=$enableval fi @@ -152,7 +152,7 @@ index 2f62662..cae212f 100644 # Check whether --enable-mem-scramble was given. if test "${enable_mem_scramble+set}" = set; then : -@@ -3216,10 +3225,11 @@ fi +@@ -3254,10 +3263,11 @@ fi @@ -168,11 +168,11 @@ index 2f62662..cae212f 100644 if test $opt_alias = yes; then $as_echo "#define ALIAS 1" >>confdefs.h -diff --git a/bash-5.0/configure.ac b/bash-5.0/configure.ac -index 52b4cdb..8070b94 100644 ---- a/bash-5.0/configure.ac -+++ b/bash-5.0/configure.ac -@@ -185,6 +185,7 @@ opt_dircomplete_expand_default=no +diff --git a/bash-5.1/configure.ac b/bash-5.1/configure.ac +index 2fe3e7d..0064683 100644 +--- a/bash-5.1/configure.ac ++++ b/bash-5.1/configure.ac +@@ -182,6 +182,7 @@ opt_dircomplete_expand_default=no opt_globascii_default=yes opt_function_import=yes opt_dev_fd_stat_broken=no @@ -180,7 +180,7 @@ index 52b4cdb..8070b94 100644 dnl options that affect how bash is compiled and linked opt_static_link=no -@@ -206,6 +207,7 @@ if test $opt_minimal_config = yes; then +@@ -203,6 +204,7 @@ if test $opt_minimal_config = yes; then opt_multibyte=yes opt_cond_regexp=no opt_coproc=no opt_casemod_attrs=no opt_casemod_expansions=no opt_extglob_default=no opt_globascii_default=yes @@ -188,7 +188,7 @@ index 52b4cdb..8070b94 100644 fi AC_ARG_ENABLE(alias, AC_HELP_STRING([--enable-alias], [enable shell aliases]), opt_alias=$enableval) -@@ -245,6 +247,7 @@ AC_ARG_ENABLE(single-help-strings, AC_HELP_STRING([--enable-single-help-strings] +@@ -242,6 +244,7 @@ AC_ARG_ENABLE(single-help-strings, AC_HELP_STRING([--enable-single-help-strings] AC_ARG_ENABLE(strict-posix-default, AC_HELP_STRING([--enable-strict-posix-default], [configure bash to be posix-conformant by default]), opt_strict_posix=$enableval) AC_ARG_ENABLE(usg-echo-default, AC_HELP_STRING([--enable-usg-echo-default], [a synonym for --enable-xpg-echo-default]), opt_xpg_echo=$enableval) AC_ARG_ENABLE(xpg-echo-default, AC_HELP_STRING([--enable-xpg-echo-default], [make the echo builtin expand escape sequences by default]), opt_xpg_echo=$enableval) @@ -196,7 +196,7 @@ index 52b4cdb..8070b94 100644 dnl options that alter how bash is compiled and linked AC_ARG_ENABLE(mem-scramble, AC_HELP_STRING([--enable-mem-scramble], [scramble memory on calls to malloc and free]), opt_memscramble=$enableval) -@@ -263,6 +266,13 @@ dnl opt_readline and opt_history are handled later, because AC_PROG_CC needs +@@ -260,6 +263,13 @@ dnl opt_readline and opt_history are handled later, because AC_PROG_CC needs dnl to be run before we can check the version of an already-installed readline dnl library @@ -210,10 +210,10 @@ index 52b4cdb..8070b94 100644 if test $opt_alias = yes; then AC_DEFINE(ALIAS) fi -diff --git a/bash-5.0/execute_cmd.c b/bash-5.0/execute_cmd.c -index 8b3c83a..5485fd9 100644 ---- a/bash-5.0/execute_cmd.c -+++ b/bash-5.0/execute_cmd.c +diff --git a/bash-5.1/execute_cmd.c b/bash-5.1/execute_cmd.c +index d2a0dd7..fb05489 100644 +--- a/bash-5.1/execute_cmd.c ++++ b/bash-5.1/execute_cmd.c @@ -82,6 +82,10 @@ extern int errno; # include "test.h" #endif @@ -225,7 +225,7 @@ index 8b3c83a..5485fd9 100644 #include "builtins/common.h" #include "builtins/builtext.h" /* list of builtins */ -@@ -5458,6 +5462,18 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, +@@ -5592,6 +5596,18 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out, leave it there, in the same format that the user used to type it in. */ args = strvec_from_word_list (words, 0, 0, (int *)NULL); @@ -244,11 +244,11 @@ index 8b3c83a..5485fd9 100644 exit (shell_execve (command, args, export_env)); } else -diff --git a/bash-5.0/plugin.c b/bash-5.0/plugin.c +diff --git a/bash-5.1/plugin.c b/bash-5.1/plugin.c new file mode 100644 index 0000000..df72830 --- /dev/null -+++ b/bash-5.0/plugin.c ++++ b/bash-5.1/plugin.c @@ -0,0 +1,428 @@ +/* plugin.c -- Bash plugin support. */ + @@ -678,11 +678,11 @@ index 0000000..df72830 + return invoke_loaded_plugins(user, shell_level, cmd, argv); + } +} -diff --git a/bash-5.0/plugin.h b/bash-5.0/plugin.h +diff --git a/bash-5.1/plugin.h b/bash-5.1/plugin.h new file mode 100644 index 0000000..116b2c5 --- /dev/null -+++ b/bash-5.0/plugin.h ++++ b/bash-5.1/plugin.h @@ -0,0 +1,79 @@ +/* plugin.h - functions from plugin.c. */ + @@ -763,10 +763,10 @@ index 0000000..116b2c5 +extern int invoke_plugin_on_shell_execve __P((char *, char *, char **)); + +#endif /* _PLUGIN_H_ */ -diff --git a/bash-5.0/shell.c b/bash-5.0/shell.c -index a2b2a55..1eedf31 100644 ---- a/bash-5.0/shell.c -+++ b/bash-5.0/shell.c +diff --git a/bash-5.1/shell.c b/bash-5.1/shell.c +index ce8087f..6928208 100644 +--- a/bash-5.1/shell.c ++++ b/bash-5.1/shell.c @@ -46,6 +46,10 @@ # include #endif @@ -778,7 +778,7 @@ index a2b2a55..1eedf31 100644 #include "bashintl.h" #define NEED_SH_SETLINEBUF_DECL /* used in externs.h */ -@@ -561,6 +565,10 @@ main (argc, argv, env) +@@ -567,6 +571,10 @@ main (argc, argv, env) if (shopt_alist) run_shopt_alist (); @@ -789,7 +789,7 @@ index a2b2a55..1eedf31 100644 /* From here on in, the shell must be a normal functioning shell. Variables from the environment are expected to be set, etc. */ shell_initialize (); -@@ -804,6 +812,10 @@ main (argc, argv, env) +@@ -810,6 +818,10 @@ main (argc, argv, env) /* Read commands until exit condition. */ reader_loop (); exit_shell (last_command_exit_value);