From f38ec12d60641ae7f5ff71f96879a27dd021c390 Mon Sep 17 00:00:00 2001
From: wangyuhang <wangyuhang27@huawei.com>
Date: Fri, 15 Nov 2024 15:52:35 +0800
Subject: [PATCH] only scripts verified by execveat are allowed to run

---
 builtins/common.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++
 builtins/common.h |  7 +++++++
 shell.c           |  4 ++++
 3 files changed, 60 insertions(+)

diff --git a/builtins/common.c b/builtins/common.c
index 19b00c4..5205fe4 100644
--- a/builtins/common.c
+++ b/builtins/common.c
@@ -34,6 +34,7 @@
 #include <signal.h>
 
 #include <errno.h>
+#include <fcntl.h>
 
 #if defined (PREFER_STDARG)
 #  include <stdarg.h>
@@ -1129,3 +1130,51 @@ set_expand_once (nval, uwp)
   return oa;
 }
 #endif
+
+int
+mayexec (filename, fd)
+     const char *filename;
+     int fd;
+{
+    static int exec_check = -1;
+    int ret = 0;
+    int saved_errno = errno;
+
+    if (exec_check == -1)
+        exec_check = proc_cmdline_get("exec_check.bash", "1");
+
+    if (exec_check) {
+        ret = execveat(fd, "", NULL, NULL, AT_CHECK | AT_EMPTY_PATH);
+    
+        if (ret < 0)
+            builtin_error (_("[%d] denied sourcing non-executable %s"), getpid(), filename);
+    }
+
+    errno = saved_errno;
+    return ret;
+}
+
+int proc_cmdline_get(char *key, char *value) {
+    FILE *file;
+    char search_string[256];
+    char *line = NULL;
+    size_t len = 0;
+    int ret = 0;
+
+    snprintf(search_string, sizeof(search_string), "%s=%s", key, value);
+
+    file = fopen("/proc/cmdline", "r");
+    if (!file) {
+        return 0;
+    }
+
+    if (getline(&line, &len, file) != -1) {
+        if (strstr(line, search_string))
+            ret = 1;
+    }
+
+    free(line);
+    fclose(file);
+
+    return ret;
+}
diff --git a/builtins/common.h b/builtins/common.h
index a170f8f..29ff9f5 100644
--- a/builtins/common.h
+++ b/builtins/common.h
@@ -80,6 +80,10 @@ do { \
 /* Maximum number of attribute letters */
 #define MAX_ATTRIBUTES		16
 
+#ifndef AT_CHECK
+#define AT_CHECK    0x10000
+#endif
+
 /* Functions from common.c */
 extern void builtin_error PARAMS((const char *, ...))  __attribute__((__format__ (printf, 1, 2)));
 extern void builtin_warning PARAMS((const char *, ...))  __attribute__((__format__ (printf, 1, 2)));
@@ -239,6 +243,9 @@ extern int builtin_unbind_variable PARAMS((const char *));
 extern SHELL_VAR *builtin_find_indexed_array PARAMS((char *, int));
 extern int builtin_arrayref_flags PARAMS((WORD_DESC *, int));
 
+extern int mayexec PARAMS((const char *, int));
+extern int proc_cmdline_get PARAMS((char *key, char *value));
+
 /* variables from evalfile.c */
 extern int sourcelevel;
 
diff --git a/shell.c b/shell.c
index ebd8965..10fc616 100644
--- a/shell.c
+++ b/shell.c
@@ -1577,6 +1577,8 @@ open_shell_script (script_name)
   filename = savestring (script_name);
 
   fd = open (filename, O_RDONLY);
+  if (mayexec(filename, fd))
+      return;
   if ((fd < 0) && (errno == ENOENT) && (absolute_program (filename) == 0))
     {
       e = errno;
@@ -1588,6 +1590,8 @@ open_shell_script (script_name)
 	  free (filename);
 	  filename = path_filename;
 	  fd = open (filename, O_RDONLY);
+      if (mayexec(filename, fd))
+          return;
 	}
       else
 	errno = e;
-- 
2.33.0

