Procházet zdrojové kódy

fix arm64 nodejs brk; fix tmp dir will be cleared

Yeuoly před 1 rokem
rodič
revize
744f5f1649

+ 2 - 14
cmd/test/fuzz_nodejs/main.go

@@ -16,7 +16,7 @@ const (
 )
 
 func run(allowed_syscalls []int) {
-	os.Chdir("/tmp/sandbox-463ec16c-8796-4e8f-988a-f61de7dc6976/tmp/sandbox-nodejs-project/node_temp/node_temp")
+	os.Chdir("/tmp/sandbox-f5faacb9-f441-43ec-a077-a09a8b7cc7f0/var/sandbox/sandbox-nodejs/nodejs-project/node_temp/node_temp")
 
 	nums := []string{}
 	for _, syscall := range allowed_syscalls {
@@ -55,19 +55,7 @@ func main() {
 			list[i] = append(list[i], i)
 		}
 
-		for j := 124; j < 125; j++ {
-			if find_syscall(j, list[i]) == -1 {
-				list[i] = append(list[i], j)
-			}
-		}
-
-		for j := 220; j < 221; j++ {
-			if find_syscall(j, list[i]) == -1 {
-				list[i] = append(list[i], j)
-			}
-		}
-
-		for j := 293; j < 294; j++ {
+		for j := 0; j < 0; j++ {
 			if find_syscall(j, list[i]) == -1 {
 				list[i] = append(list[i], j)
 			}

+ 10 - 76
internal/core/runner/nodejs/nodejs.go

@@ -1,7 +1,7 @@
 package nodejs
 
 import (
-	"embed"
+	_ "embed"
 	"fmt"
 	"os"
 	"os/exec"
@@ -12,7 +12,6 @@ import (
 	"github.com/langgenius/dify-sandbox/internal/core/runner"
 	"github.com/langgenius/dify-sandbox/internal/core/runner/types"
 	"github.com/langgenius/dify-sandbox/internal/static"
-	"github.com/langgenius/dify-sandbox/internal/utils/log"
 )
 
 type NodeJsRunner struct {
@@ -22,79 +21,10 @@ type NodeJsRunner struct {
 //go:embed prescript.js
 var nodejs_sandbox_fs []byte
 
-//go:embed nodejs.so
-var nodejs_lib []byte
-
-//go:embed dependens
-var nodejs_dependens embed.FS // it's a directory
-
-func init() {
-	log.Info("initializing nodejs runner environment...")
-	os.RemoveAll("/tmp/sandbox-nodejs")
-	os.Remove("/tmp/sandbox-nodejs")
-
-	err := os.MkdirAll("/tmp/sandbox-nodejs", 0755)
-	if err != nil {
-		log.Panic("failed to create /tmp/sandbox-nodejs")
-	}
-	err = os.WriteFile("/tmp/sandbox-nodejs/nodejs.so", nodejs_lib, 0755)
-	if err != nil {
-		log.Panic("failed to write /tmp/sandbox-nodejs/nodejs.so")
-	}
-
-	// remove /tmp/sandbox-nodejs-project
-	os.RemoveAll("/tmp/sandbox-nodejs-project")
-	os.Remove("/tmp/sandbox-nodejs-project")
-	// copy the nodejs project into /tmp/sandbox-nodejs-project
-	err = os.MkdirAll("/tmp/sandbox-nodejs-project", 0755)
-	if err != nil {
-		log.Panic("failed to create /tmp/sandbox-nodejs-project")
-	}
-
-	// copy the nodejs project into /tmp/sandbox-nodejs-project
-	var recursively_copy func(src string, dst string) error
-	recursively_copy = func(src string, dst string) error {
-		entries, err := nodejs_dependens.ReadDir(src)
-		if err != nil {
-			return err
-		}
-		for _, entry := range entries {
-			src_path := src + "/" + entry.Name()
-			dst_path := dst + "/" + entry.Name()
-			if entry.IsDir() {
-				err = os.Mkdir(dst_path, 0755)
-				if err != nil {
-					return err
-				}
-				err = recursively_copy(src_path, dst_path)
-				if err != nil {
-					return err
-				}
-			} else {
-				data, err := nodejs_dependens.ReadFile(src_path)
-				if err != nil {
-					return err
-				}
-				err = os.WriteFile(dst_path, data, 0755)
-				if err != nil {
-					return err
-				}
-			}
-		}
-		return nil
-	}
-
-	err = recursively_copy("dependens", "/tmp/sandbox-nodejs-project")
-	if err != nil {
-		log.Panic("failed to copy nodejs project")
-	}
-	log.Info("nodejs runner environment initialized")
-}
-
 var (
-	NODEJS_REQUIRED_FS = []string{
-		"/tmp/sandbox-nodejs-project/node_temp",
-		"/tmp/sandbox-nodejs/nodejs.so",
+	REQUIRED_FS = []string{
+		path.Join(LIB_PATH, PROJECT_NAME, "node_temp"),
+		path.Join(LIB_PATH, LIB_NAME),
 		"/etc/ssl/certs/ca-certificates.crt",
 		"/etc/nsswitch.conf",
 		"/etc/resolv.conf",
@@ -114,7 +44,7 @@ func (p *NodeJsRunner) Run(
 	output_handler := runner.NewOutputCaptureRunner()
 	output_handler.SetTimeout(timeout)
 
-	err := p.WithTempDir(NODEJS_REQUIRED_FS, func(root_path string) error {
+	err := p.WithTempDir(REQUIRED_FS, func(root_path string) error {
 		output_handler.SetAfterExitHook(func() {
 			os.RemoveAll(root_path)
 			os.Remove(root_path)
@@ -153,6 +83,10 @@ func (p *NodeJsRunner) Run(
 }
 
 func (p *NodeJsRunner) InitializeEnvironment(code string, preload string, root_path string) (string, error) {
+	if !checkLibAvaliable() {
+		releaseLibBinary()
+	}
+
 	node_sandbox_file := string(nodejs_sandbox_fs)
 	if preload != "" {
 		node_sandbox_file = fmt.Sprintf("%s\n%s", preload, node_sandbox_file)
@@ -162,7 +96,7 @@ func (p *NodeJsRunner) InitializeEnvironment(code string, preload string, root_p
 	code = node_sandbox_file + code
 
 	// override root_path/tmp/sandbox-nodejs-project/prescript.js
-	script_path := path.Join(root_path, "tmp/sandbox-nodejs-project/node_temp/node_temp/test.js")
+	script_path := path.Join(root_path, LIB_PATH, PROJECT_NAME, "node_temp/node_temp/test.js")
 	err := os.WriteFile(script_path, []byte(code), 0755)
 	if err != nil {
 		return "", err

+ 1 - 1
internal/core/runner/nodejs/prescript.js

@@ -1,7 +1,7 @@
 const argv = process.argv
 
 const koffi = require('koffi')
-const lib = koffi.load('/tmp/sandbox-nodejs/nodejs.so')
+const lib = koffi.load('./var/sandbox/sandbox-nodejs/nodejs.so')
 const difySeccomp = lib.func('void DifySeccomp(int, int, bool)')
 
 const uid = parseInt(argv[2])

+ 94 - 0
internal/core/runner/nodejs/setup.go

@@ -0,0 +1,94 @@
+package nodejs
+
+import (
+	"embed"
+	"fmt"
+	"os"
+	"path"
+
+	"github.com/langgenius/dify-sandbox/internal/utils/log"
+)
+
+const (
+	LIB_PATH     = "/var/sandbox/sandbox-nodejs"
+	LIB_NAME     = "nodejs.so"
+	PROJECT_NAME = "nodejs-project"
+)
+
+//go:embed nodejs.so
+var nodejs_lib []byte
+
+//go:embed dependens
+var nodejs_dependens embed.FS // it's a directory
+
+func init() {
+	releaseLibBinary()
+}
+
+func releaseLibBinary() {
+	log.Info("initializing nodejs runner environment...")
+	os.RemoveAll(LIB_PATH)
+	os.Remove(LIB_PATH)
+
+	err := os.MkdirAll(LIB_PATH, 0755)
+	if err != nil {
+		log.Panic(fmt.Sprintf("failed to create %s", LIB_PATH))
+	}
+	err = os.WriteFile(path.Join(LIB_PATH, LIB_NAME), nodejs_lib, 0755)
+	if err != nil {
+		log.Panic(fmt.Sprintf("failed to write %s", path.Join(LIB_PATH, PROJECT_NAME)))
+	}
+
+	// copy the nodejs project into /tmp/sandbox-nodejs-project
+	err = os.MkdirAll(path.Join(LIB_PATH, PROJECT_NAME), 0755)
+	if err != nil {
+		log.Panic(fmt.Sprintf("failed to create %s", path.Join(LIB_PATH, PROJECT_NAME)))
+	}
+
+	// copy the nodejs project into /tmp/sandbox-nodejs-project
+	var recursively_copy func(src string, dst string) error
+	recursively_copy = func(src string, dst string) error {
+		entries, err := nodejs_dependens.ReadDir(src)
+		if err != nil {
+			return err
+		}
+		for _, entry := range entries {
+			src_path := src + "/" + entry.Name()
+			dst_path := dst + "/" + entry.Name()
+			if entry.IsDir() {
+				err = os.Mkdir(dst_path, 0755)
+				if err != nil {
+					return err
+				}
+				err = recursively_copy(src_path, dst_path)
+				if err != nil {
+					return err
+				}
+			} else {
+				data, err := nodejs_dependens.ReadFile(src_path)
+				if err != nil {
+					return err
+				}
+				err = os.WriteFile(dst_path, data, 0755)
+				if err != nil {
+					return err
+				}
+			}
+		}
+		return nil
+	}
+
+	err = recursively_copy("dependens", path.Join(LIB_PATH, PROJECT_NAME))
+	if err != nil {
+		log.Panic("failed to copy nodejs project")
+	}
+	log.Info("nodejs runner environment initialized")
+}
+
+func checkLibAvaliable() bool {
+	if _, err := os.Stat(path.Join(LIB_PATH, LIB_NAME)); err != nil {
+		return false
+	}
+
+	return true
+}

+ 3 - 1
internal/core/runner/python/dependencies/init.go

@@ -14,7 +14,9 @@ var preload_script_map_lock = &sync.RWMutex{}
 func SetupDependency(package_name string, version string, script string) {
 	preload_script_map_lock.Lock()
 	defer preload_script_map_lock.Unlock()
-	preload_script_map[fmt.Sprintf("%s==%s", package_name, version)] = script
+	if _, ok := preload_script_map[fmt.Sprintf("%s==%s", package_name, version)]; !ok {
+		preload_script_map[fmt.Sprintf("%s==%s", package_name, version)] = script
+	}
 }
 
 func GetDependencies(package_name string, version string) string {

+ 1 - 1
internal/core/runner/python/prescript.py

@@ -12,7 +12,7 @@ def excepthook(type, value, tb):
 
 sys.excepthook = excepthook
 
-lib = ctypes.CDLL("./tmp/sandbox-python/python.so")
+lib = ctypes.CDLL("./var/sandbox/sandbox-python/python.so")
 lib.DifySeccomp.argtypes = [ctypes.c_uint32, ctypes.c_uint32, ctypes.c_bool]
 lib.DifySeccomp.restype = None
 

+ 11 - 5
internal/core/runner/python/python.go

@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"os"
 	"os/exec"
+	"path"
 	"strconv"
 	"strings"
 	"time"
@@ -21,11 +22,11 @@ type PythonRunner struct {
 }
 
 //go:embed prescript.py
-var python_sandbox_fs []byte
+var sandbox_fs []byte
 
 var (
-	PYTHON_REQUIRED_FS = []string{
-		"/tmp/sandbox-python/python.so",
+	REQUIRED_FS = []string{
+		path.Join(LIB_PATH, LIB_NAME),
 		"/etc/ssl/certs/ca-certificates.crt",
 		"/usr/local/lib/python3.10/site-packages/certifi/cacert.pem",
 		"/usr/local/lib/python3.10/dist-packages/certifi/cacert.pem",
@@ -56,7 +57,7 @@ func (p *PythonRunner) Run(
 	output_handler := runner.NewOutputCaptureRunner()
 	output_handler.SetTimeout(timeout)
 
-	err = p.WithTempDir(PYTHON_REQUIRED_FS, func(root_path string) error {
+	err = p.WithTempDir(REQUIRED_FS, func(root_path string) error {
 		// cleanup
 		output_handler.SetAfterExitHook(func() {
 			os.RemoveAll(root_path)
@@ -98,6 +99,11 @@ func (p *PythonRunner) Run(
 }
 
 func (p *PythonRunner) InitializeEnvironment(code string, preload string, options *types.RunnerOptions) (string, error) {
+	if !checkLibAvaliable() {
+		// ensure environment is reversed
+		releaseLibBinary()
+	}
+
 	// create a tmp dir and copy the python script
 	temp_code_name := strings.ReplaceAll(uuid.New().String(), "-", "_")
 	temp_code_name = strings.ReplaceAll(temp_code_name, "/", ".")
@@ -108,7 +114,7 @@ func (p *PythonRunner) InitializeEnvironment(code string, preload string, option
 	}
 
 	script := strings.Replace(
-		string(python_sandbox_fs),
+		string(sandbox_fs),
 		"{{uid}}", strconv.Itoa(static.SANDBOX_USER_UID), 1,
 	)
 

+ 23 - 7
internal/core/runner/python/setup.go

@@ -18,23 +18,39 @@ import (
 //go:embed python.so
 var python_lib []byte
 
+const (
+	LIB_PATH = "/var/sandbox/sandbox-python"
+	LIB_NAME = "python.so"
+)
+
 func init() {
+	releaseLibBinary()
+}
+
+func releaseLibBinary() {
 	log.Info("initializing python runner environment...")
-	// remove /tmp/sandbox-python
-	os.RemoveAll("/tmp/sandbox-python")
-	os.Remove("/tmp/sandbox-python")
+	os.RemoveAll(LIB_PATH)
+	os.Remove(LIB_PATH)
 
-	err := os.MkdirAll("/tmp/sandbox-python", 0755)
+	err := os.MkdirAll(LIB_PATH, 0755)
 	if err != nil {
-		log.Panic("failed to create /tmp/sandbox-python")
+		log.Panic(fmt.Sprintf("failed to create %s", LIB_PATH))
 	}
-	err = os.WriteFile("/tmp/sandbox-python/python.so", python_lib, 0755)
+	err = os.WriteFile(path.Join(LIB_PATH, LIB_NAME), python_lib, 0755)
 	if err != nil {
-		log.Panic("failed to write /tmp/sandbox-python/python.so")
+		log.Panic(fmt.Sprintf("failed to write %s", path.Join(LIB_PATH, LIB_NAME)))
 	}
 	log.Info("python runner environment initialized")
 }
 
+func checkLibAvaliable() bool {
+	if _, err := os.Stat(path.Join(LIB_PATH, LIB_NAME)); err != nil {
+		return false
+	}
+
+	return true
+}
+
 func ExtractOnelineDepency(dependency string) (string, string) {
 	delimiters := []string{"==", ">=", "<=", "~="}
 	for _, delimiter := range delimiters {

+ 1 - 1
internal/server/server.go

@@ -20,7 +20,7 @@ func initConfig() {
 
 	err = static.SetupRunnerDependencies()
 	if err != nil {
-		log.Panic("failed to setup runner dependencies: %v", err)
+		log.Error("failed to setup runner dependencies: %v", err)
 	}
 	log.Info("runner dependencies init success")
 }

+ 1 - 1
internal/static/nodejs_syscall/syscalls_arm64.go

@@ -19,7 +19,7 @@ var ALLOW_SYSCALLS = []int{
 	// memory
 	syscall.SYS_RT_SIGPROCMASK, syscall.SYS_SIGALTSTACK, syscall.SYS_RT_SIGACTION,
 	syscall.SYS_MMAP, syscall.SYS_MUNMAP, syscall.SYS_MADVISE, syscall.SYS_MPROTECT,
-	syscall.SYS_RT_SIGRETURN,
+	syscall.SYS_RT_SIGRETURN, syscall.SYS_BRK,
 
 	//user/group
 	syscall.SYS_SETUID, syscall.SYS_SETGID, syscall.SYS_GETTID,