[RFC PATCH] sed/grep noexec support for performance optimization

chunhui ren via busybox <[email protected]>
Newsgroups gmane.linux.busybox
Message-ID <SEZPR01MB5942F25CBE52D13F1F13F2E8C497A@SEZPR01MB5942.apcprd01.prod.exchangelabs.com>
Hi BusyBox maintainers,


I’m working on a performance optimization and would like to explore adding

noexec support for sed and grep.


The motivation is to reduce fork/exec overhead in constrained environments

by executing sed/grep in-process when they are invoked via BusyBox applet

dispatch (similar in spirit to existing noexec-related optimizations).


I have an initial implementation attached below, where:

• sed and grep are marked as noexec-capable applets

• the change is intended purely as a performance optimization


Before refining or splitting this further, I’d like to confirm whether this

direction is acceptable, and whether there are known concerns in sed/grep

internals that would make noexec unsuitable.


Thanks for your time and feedback.


Signed-off-by: Ren Chunhui <[email protected]<mailto:[email protected]>>


 editors/sed.c     |  2 +-

 findutils/grep.c  |  2 +-
 include/libbb.h   |  2 ++
 libbb/appletlib.c | 29 +++++++++++++++++++++++++++++
 shell/ash.c       |  2 +-
 5 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/editors/sed.c b/editors/sed.c
index 6179c5e..10fb3d9 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -60,7 +60,7 @@
 //config:  sed is used to perform text transformations on a file
 //config:  or input from a pipeline.

-//applet:IF_SED(APPLET(sed, BB_DIR_BIN, BB_SUID_DROP))
+//applet:IF_SED(APPLET_NOEXEC(sed, sed, BB_DIR_BIN, BB_SUID_DROP, sed))

 //kbuild:lib-$(CONFIG_SED) += sed.o

diff --git a/findutils/grep.c b/findutils/grep.c
index f6d0a73..7cb89da 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -44,7 +44,7 @@
 //config:  context surrounding our matching lines.
 //config:  Print the specified number of context lines (-C).

-//applet:IF_GREP(APPLET(grep, BB_DIR_BIN, BB_SUID_DROP))
+//applet:IF_GREP(APPLET_NOEXEC(grep, grep, BB_DIR_BIN, BB_SUID_DROP, grep))
 //                APPLET_ODDNAME:name   main  location    suid_type     help
 //applet:IF_EGREP(APPLET_ODDNAME(egrep, grep, BB_DIR_BIN, BB_SUID_DROP, egrep))
 //applet:IF_FGREP(APPLET_ODDNAME(fgrep, grep, BB_DIR_BIN, BB_SUID_DROP, fgrep))

diff --git a/include/libbb.h b/include/libbb.h
index 01cdb1b..6704213 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -2658,6 +2658,8 @@ void bbunit_settestfailed(void);
            } \
      } while (0)

+extern bool is_applet_forbidden_noexec(int applet_no);
+extern bool is_applet_force_noexec(int applet_no);

 POP_SAVED_FUNCTION_VISIBILITY

diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index d9cc484..915049d 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -1129,3 +1129,32 @@ int main(int argc UNUSED_PARAM, char **argv)

 #endif
 }
+
+static bool is_forbidden_noexec[NUM_APPLETS] = {
+     [66]  = true, // APPLET_NO_gzip
+     [140] = true, // APPLET_NO_ps
+     [85]  = true, // APPLET_NO_ip
+     [183] = true, // APPLET_NO_top
+     [106] = true, // APPLET_NO_lsattr
+     [177] = true, // APPLET_NO_taskset
+};
+
+bool is_applet_forbidden_noexec(int applet_no)
+{
+     if (applet_no < 0 || applet_no >= NUM_APPLETS)
+           return false;
+     return is_forbidden_noexec[applet_no];
+}
+
+static bool is_force_noexec[NUM_APPLETS] = {
+     [6]   = true, // APPLET_NO_awk
+     //[63] = true, // APPLET_NO_grep
+     [157] = true, // APPLET_NO_sed
+};
+
+bool is_applet_force_noexec(int applet_no)
+{
+     if (applet_no < 0 || applet_no >= NUM_APPLETS)
+           return false;
+     return is_force_noexec[applet_no];
+}

diff --git a/shell/ash.c b/shell/ash.c
index bbd7307..8e83dab 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -8336,7 +8336,7 @@ static void shellexec(char *prog, char **argv, const char *path, int idx)
      envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
      if (strchr(prog, '/') != NULL
 #if ENABLE_FEATURE_SH_STANDALONE
-      || (applet_no = find_applet_by_name(prog)) >= 0
+      || (((applet_no = find_applet_by_name(prog)) >= 0)
+          && !is_applet_forbidden_noexec(applet_no)
+          && is_applet_force_noexec(applet_no))
 #endif
      ) {
            tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
--
2.37.7

_______________________________________________
busybox mailing list
[email protected]
https://lists.busybox.net/mailman/listinfo/busybox
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.