Yeuoly 1 年之前
父节点
当前提交
897bcf0b57

+ 58 - 21
cmd/test/fuzz_python/main.go

@@ -12,21 +12,31 @@ import (
 )
 
 const (
-	SYSCALL_NUMS = 400
+	SYSCALL_NUMS = 500
 )
 
-func run(allowed_syscalls []int) {
-	// os.Chdir("/tmp/123")
+var (
+	total_rans      = 0
+	total_rans_lock = sync.Mutex{}
+)
+
+func run(allowed_syscalls []int) error {
+	total_rans_lock.Lock()
+	total_rans++
+	total_rans_lock.Unlock()
 
 	nums := []string{}
 	for _, syscall := range allowed_syscalls {
 		nums = append(nums, strconv.Itoa(syscall))
 	}
 	os.Setenv("ALLOWED_SYSCALLS", strings.Join(nums, ","))
-	_, err := exec.Command("python3", ".test.py").Output()
+	cmd := exec.Command("python3", "cmd/test/fuzz_python_amd64/test.py")
+	cmd.Stderr = os.Stderr
+	_, err := cmd.Output()
 	if err == nil {
+		return nil
 	} else {
-		fmt.Println("failed")
+		return err
 	}
 }
 
@@ -39,27 +49,16 @@ func find_syscall(syscall int, syscalls []int) int {
 	return -1
 }
 
-func main() {
+func fuzz_range(r []int) bool {
 	original := python_syscall.ALLOW_SYSCALLS
 	original = append(original, python_syscall.ALLOW_NETWORK_SYSCALLS...)
 
 	// generate task list
-	list := make([][]int, SYSCALL_NUMS)
-	for i := 0; i < SYSCALL_NUMS; i++ {
+	list := make([][]int, 10)
+	for i := 0; i < 10; i++ {
 		list[i] = make([]int, len(original))
 		copy(list[i], original)
-		// add i
-		if find_syscall(i, original) == -1 {
-			list[i] = append(list[i], i)
-		}
-
-		for j := 22; j < 23; j++ {
-			if find_syscall(j, list[i]) == -1 {
-				list[i] = append(list[i], j)
-			}
-		}
-
-		for j := 124; j < 125; j++ {
+		for _, j := range r {
 			if find_syscall(j, list[i]) == -1 {
 				list[i] = append(list[i], j)
 			}
@@ -71,6 +70,7 @@ func main() {
 	i := 0
 
 	// run 4 tasks concurrently
+	failed := false
 	for j := 0; j < 4; j++ {
 		wg.Add(1)
 		go func() {
@@ -84,11 +84,48 @@ func main() {
 				task := list[i]
 				i++
 				lock.Unlock()
-				run(task)
+				if run(task) != nil {
+					failed = true
+					// stop all tasks
+					lock.Lock()
+					i = len(list)
+					lock.Unlock()
+				}
 			}
 		}()
 	}
 
 	// wait for all tasks to finish
 	wg.Wait()
+
+	return !failed
+}
+
+func fuzz() {
+	unnecessary_syscalls := []int{}
+
+	for i := 0; i < SYSCALL_NUMS; i++ {
+		// remove syscall
+		fmt.Println(i)
+		nr := []int{}
+		for j := 0; j < SYSCALL_NUMS; j++ {
+			// skip i and unnecessary syscalls
+			if i != j && find_syscall(j, unnecessary_syscalls) == -1 &&
+				find_syscall(j, python_syscall.ALLOW_SYSCALLS) == -1 &&
+				find_syscall(j, python_syscall.ALLOW_NETWORK_SYSCALLS) == -1 {
+				nr = append(nr, j)
+			}
+		}
+
+		if fuzz_range(nr) {
+			unnecessary_syscalls = append(unnecessary_syscalls, i)
+		} else {
+			fmt.Printf("syscall %d is necessary\n", i)
+		}
+	}
+}
+
+func main() {
+	fuzz()
+	fmt.Printf("Total rans: %d\n", total_rans)
 }

+ 0 - 2
cmd/test/fuzz_python_amd64/main.go

@@ -16,8 +16,6 @@ const (
 )
 
 func run(allowed_syscalls []int) {
-	// os.Chdir("/tmp/123")
-
 	nums := []string{}
 	for _, syscall := range allowed_syscalls {
 		nums = append(nums, strconv.Itoa(syscall))

+ 2 - 22
cmd/test/fuzz_python_amd64/test.py

@@ -2,7 +2,6 @@ import ctypes
 import os
 import sys
 import json
-import time
 import traceback
 
 # setup sys.excepthook
@@ -13,39 +12,20 @@ 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
 
 
 import json
-import base64
-import subprocess
 import os
 
 import json
-import datetime
-from datetime import datetime
-datetime.strptime('2021-01-01', '%Y-%m-%d')
-import math
-import random
-import re
-import string
 import sys
-import time
 import traceback
-import uuid
 import os
-import base64
-import hashlib
-import hmac
-import binascii
-import collections
-import functools
-import operator
-import itertools
 
-os.chdir("/")
+os.chdir("/var/sandbox/sandbox-python")
 
 lib.DifySeccomp(65537, 1001, 1)
 

+ 24 - 0
cmd/test/python/main.go

@@ -0,0 +1,24 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/langgenius/dify-sandbox/internal/core/runner/python"
+	"github.com/langgenius/dify-sandbox/internal/core/runner/types"
+	"github.com/langgenius/dify-sandbox/internal/service"
+	"github.com/langgenius/dify-sandbox/internal/static"
+)
+
+func main() {
+	static.InitConfig("conf/config.yaml")
+	python.PreparePythonDependenciesEnv()
+	resp := service.RunPython3Code(`import httpx
+print(httpx.get("https://www.bilibili.com").text)`,
+		``,
+		&types.RunnerOptions{
+			EnableNetwork: true,
+			Dependencies:  []types.Dependency{},
+		})
+
+	fmt.Println(resp.Data)
+}

+ 5 - 0
internal/controller/router.go

@@ -19,4 +19,9 @@ func Setup(eng *gin.Engine) {
 		"/v1/sandbox/dependencies",
 		GetDependencies,
 	)
+
+	eng.POST(
+		"/v1/sandbox/dependencies/update",
+		UpdateDependencies,
+	)
 }

+ 13 - 0
internal/controller/run.go

@@ -43,3 +43,16 @@ func GetDependencies(c *gin.Context) {
 		}
 	})
 }
+
+func UpdateDependencies(c *gin.Context) {
+	BindRequest(c, func(req struct {
+		Language string `json:"language" form:"language" binding:"required"`
+	}) {
+		switch req.Language {
+		case "python3":
+			c.JSON(200, service.UpdateDependencies())
+		default:
+			c.JSON(400, types.ErrorResponse(-400, "unsupported language"))
+		}
+	})
+}

+ 1 - 1
internal/core/runner/nodejs/nodejs.go

@@ -44,7 +44,7 @@ func (p *NodeJsRunner) Run(
 	output_handler := runner.NewOutputCaptureRunner()
 	output_handler.SetTimeout(timeout)
 
-	err := p.WithTempDir(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)

+ 0 - 46
internal/core/runner/python/dependencies/generic.go

@@ -1,46 +0,0 @@
-package dependencies
-
-/*
-import json
-import datetime
-import math
-import random
-import re
-import string
-import sys
-import time
-import traceback
-import uuid
-import os
-import base64
-import hashlib
-import hmac
-import binascii
-import collections
-import functools
-import operator
-import itertools
-*/
-
-func init() {
-	SetupDependency("json", "", "import json")
-	SetupDependency("datetime", "", "import datetime\nfrom datetime import datetime\ndatetime.strptime('2021-01-01', '%Y-%m-%d')")
-	SetupDependency("math", "", "import math")
-	SetupDependency("random", "", "import random")
-	SetupDependency("re", "", "import re")
-	SetupDependency("string", "", "import string")
-	SetupDependency("sys", "", "import sys")
-	SetupDependency("time", "", "import time")
-	SetupDependency("traceback", "", "import traceback")
-	SetupDependency("uuid", "", "import uuid")
-	SetupDependency("os", "", "import os")
-	SetupDependency("base64", "", "import base64")
-	SetupDependency("hashlib", "", "import hashlib")
-	SetupDependency("hmac", "", "import hmac")
-	SetupDependency("binascii", "", "import binascii")
-	SetupDependency("collections", "", "import collections")
-	SetupDependency("functools", "", "import functools")
-	SetupDependency("operator", "", "import operator")
-	SetupDependency("itertools", "", "import itertools")
-	SetupDependency("uuid", "", "import uuid")
-}

+ 6 - 24
internal/core/runner/python/dependencies/init.go

@@ -1,8 +1,6 @@
 package dependencies
 
 import (
-	"fmt"
-	"strings"
 	"sync"
 
 	"github.com/langgenius/dify-sandbox/internal/core/runner/types"
@@ -11,39 +9,23 @@ import (
 var preload_script_map = map[string]string{}
 var preload_script_map_lock = &sync.RWMutex{}
 
-func SetupDependency(package_name string, version string, script string) {
+func SetupDependency(package_name string, version string) {
 	preload_script_map_lock.Lock()
 	defer preload_script_map_lock.Unlock()
-	if _, ok := preload_script_map[fmt.Sprintf("%s==%s", package_name, version)]; !ok {
-		preload_script_map[fmt.Sprintf("%s==%s", package_name, version)] = script
-	}
+	preload_script_map[package_name] = version
 }
 
-func GetDependencies(package_name string, version string) string {
+func GetDependency(package_name string, version string) string {
 	preload_script_map_lock.RLock()
 	defer preload_script_map_lock.RUnlock()
-	if script, ok := preload_script_map[fmt.Sprintf("%s==%s", package_name, version)]; ok {
-		return script
-	}
-
-	return ""
+	return preload_script_map[package_name]
 }
 
 func ListDependencies() []types.Dependency {
 	dependencies := []types.Dependency{}
 	preload_script_map_lock.RLock()
-	for k := range preload_script_map {
-		parts := strings.Split(k, "==")
-		package_name := ""
-		version := ""
-		if len(parts) == 0 {
-			continue
-		} else if len(parts) == 1 {
-			package_name = parts[0]
-		} else if len(parts) == 2 {
-			package_name = parts[0]
-			version = parts[1]
-		}
+	defer preload_script_map_lock.RUnlock()
+	for package_name, version := range preload_script_map {
 		dependencies = append(dependencies, types.Dependency{
 			Name:    package_name,
 			Version: version,

+ 1 - 31
internal/core/runner/python/dependencies/jinja2.go

@@ -1,35 +1,5 @@
 package dependencies
 
-import "fmt"
-
-var (
-	JINJA_PRELOAD_TEMPLATE = `{% set fruits = ['Apple'] %}
-{{ 'a' }}
-{% for fruit in fruits %}
-	<li>{{ fruit }}</li>
-{% endfor %}
-{% if fruits|length > 1 %}
-1
-{% endif %}
-{% for i in range(5) %}
-	{% if i == 3 %}{{ i }}{% else %}{% endif %}
-{% endfor %}
-	{% for i in range(3) %}
-		{{ i + 1 }}
-	{% endfor %}
-{% macro say_hello() %}a{{ 'b' }}{% endmacro %}
-{{ s }}{{ say_hello() }}`
-)
-
 func init() {
-	SetupDependency("jinja2", "", fmt.Sprintf(`import jinja2
-def _jinja2_preload_():
-	# prepare jinja2 environment, load template and render before to avoid sandbox issue
-	template = jinja2.Template('''%s''')
-	template.render(s='a')
-
-if __name__ == '__main__':
-	_jinja2_preload_()
-	`, JINJA_PRELOAD_TEMPLATE,
-	))
+	SetupDependency("jinja2", "")
 }

+ 0 - 4
internal/core/runner/python/dependencies/math.go

@@ -1,4 +0,0 @@
-package dependencies
-
-func init() {
-}

+ 2 - 2
internal/core/runner/python/dependencies/network.go

@@ -1,6 +1,6 @@
 package dependencies
 
 func init() {
-	SetupDependency("httpx", "", "import httpx\nimport encodings.idna\nimport socks")
-	SetupDependency("requests", "", "import requests\nfrom netrc import netrc, NetrcParseError\nimport urllib3\nimport socket\nimport socks")
+	SetupDependency("httpx", "")
+	SetupDependency("requests", "")
 }

+ 52 - 0
internal/core/runner/python/env.go

@@ -0,0 +1,52 @@
+package python
+
+import (
+	_ "embed"
+	"os"
+	"os/exec"
+	"path"
+
+	"github.com/langgenius/dify-sandbox/internal/core/runner"
+	"github.com/langgenius/dify-sandbox/internal/static"
+	"github.com/langgenius/dify-sandbox/internal/utils/log"
+)
+
+//go:embed env.sh
+var env_script string
+
+func PreparePythonDependenciesEnv() error {
+	config := static.GetDifySandboxGlobalConfigurations()
+
+	runner := runner.TempDirRunner{}
+	err := runner.WithTempDir("/", []string{}, func(root_path string) error {
+		err := os.WriteFile(path.Join(root_path, "env.sh"), []byte(env_script), 0755)
+		if err != nil {
+			return err
+		}
+
+		for _, lib_path := range config.PythonLibPaths {
+			// check if the lib path is available
+			if _, err := os.Stat(lib_path); err != nil {
+				log.Warn("python lib path %s is not available", lib_path)
+				continue
+			}
+			exec_cmd := exec.Command(
+				"bash",
+				path.Join(root_path, "env.sh"),
+				lib_path,
+				LIB_PATH,
+			)
+			exec_cmd.Stderr = os.Stderr
+
+			if err := exec_cmd.Run(); err != nil {
+				return err
+			}
+		}
+
+		os.RemoveAll(root_path)
+		os.Remove(root_path)
+		return nil
+	})
+
+	return err
+}

+ 53 - 0
internal/core/runner/python/env.sh

@@ -0,0 +1,53 @@
+#!/bin/bash
+
+# Check if the correct number of arguments are provided
+if [ "$#" -ne 2 ]; then
+    echo "Usage: $0 <src> <dest>"
+    exit 1
+fi
+
+src="$1"
+dest="$2"
+
+# Function to copy and link files
+copy_and_link() {
+    local src_file="$1"
+    local dest_file="$2"
+
+    if [ -L "$src_file" ]; then
+        # If src_file is a symbolic link, copy it without changing permissions
+        cp -P "$src_file" "$dest_file"
+    elif [ -b "$src_file" ] || [ -c "$src_file" ]; then
+        # If src_file is a device file, copy it and change permissions
+        cp "$src_file" "$dest_file"
+        chmod 444 "$dest_file"
+    else
+        # Otherwise, create a hard link and change the permissions to read-only
+        ln -f "$src_file" "$dest_file" 2>/dev/null || { cp "$src_file" "$dest_file" && chmod 444 "$dest_file"; }
+    fi
+}
+
+# Check if src is a file or directory
+if [ -f "$src" ]; then
+    # src is a file, create hard link directly in dest
+    mkdir -p "$(dirname "$dest/$src")"
+    copy_and_link "$src" "$dest/$src"
+elif [ -d "$src" ]; then
+    # src is a directory, process as before
+    mkdir -p "$dest/$src"
+
+    # Find all files in the source directory
+    find "$src" -type f | while read -r file; do
+        # Get the relative path of the file
+        rel_path="${file#$src/}"
+        # Get the directory of the relative path
+        rel_dir=$(dirname "$rel_path")
+        # Create the same directory structure in the destination
+        mkdir -p "$dest/$src/$rel_dir"
+        # Copy and link the file
+        copy_and_link "$file" "$dest/$src/$rel_path"
+    done
+else
+    echo "Error: $src is neither a file nor a directory"
+    exit 1
+fi

+ 7 - 2
internal/core/runner/python/prescript.py

@@ -1,8 +1,6 @@
 import ctypes
 import os
 import sys
-import json
-import time
 import traceback
 # setup sys.excepthook
 def excepthook(type, value, tb):
@@ -16,6 +14,13 @@ 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
 
+# get running path
+running_path = sys.argv[1]
+if not running_path:
+    exit(-1)
+
+os.chdir(running_path)
+
 {{preload}}
 
 lib.DifySeccomp({{uid}}, {{gid}}, {{enable_network}})

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

@@ -12,7 +12,6 @@ import (
 
 	"github.com/google/uuid"
 	"github.com/langgenius/dify-sandbox/internal/core/runner"
-	python_dependencies "github.com/langgenius/dify-sandbox/internal/core/runner/python/dependencies"
 	"github.com/langgenius/dify-sandbox/internal/core/runner/types"
 	"github.com/langgenius/dify-sandbox/internal/static"
 )
@@ -27,14 +26,6 @@ var sandbox_fs []byte
 var (
 	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",
-		"/etc/nsswitch.conf",
-		"/etc/resolv.conf",
-		"/run/systemd/resolve/stub-resolv.conf",
-		"/run/resolvconf/resolv.conf",
-		"/etc/hosts",
 	}
 )
 
@@ -57,7 +48,7 @@ func (p *PythonRunner) Run(
 	output_handler := runner.NewOutputCaptureRunner()
 	output_handler.SetTimeout(timeout)
 
-	err = p.WithTempDir(REQUIRED_FS, func(root_path string) error {
+	err = p.WithTempDir(LIB_PATH, REQUIRED_FS, func(root_path string) error {
 		// cleanup
 		output_handler.SetAfterExitHook(func() {
 			os.RemoveAll(root_path)
@@ -68,6 +59,7 @@ func (p *PythonRunner) Run(
 		cmd := exec.Command(
 			configuration.PythonPath,
 			untrusted_code_path,
+			LIB_PATH,
 		)
 		cmd.Env = []string{}
 
@@ -108,11 +100,6 @@ func (p *PythonRunner) InitializeEnvironment(code string, preload string, option
 	temp_code_name := strings.ReplaceAll(uuid.New().String(), "-", "_")
 	temp_code_name = strings.ReplaceAll(temp_code_name, "/", ".")
 
-	packages_preload := make([]string, len(options.Dependencies))
-	for i, dependency := range options.Dependencies {
-		packages_preload[i] = python_dependencies.GetDependencies(dependency.Name, dependency.Version)
-	}
-
 	script := strings.Replace(
 		string(sandbox_fs),
 		"{{uid}}", strconv.Itoa(static.SANDBOX_USER_UID), 1,
@@ -138,7 +125,7 @@ func (p *PythonRunner) InitializeEnvironment(code string, preload string, option
 	script = strings.Replace(
 		script,
 		"{{preload}}",
-		fmt.Sprintf("%s\n%s", preload, strings.Join(packages_preload, "\n")),
+		fmt.Sprintf("%s\n", preload),
 		1,
 	)
 
@@ -149,8 +136,8 @@ func (p *PythonRunner) InitializeEnvironment(code string, preload string, option
 		1,
 	)
 
-	untrusted_code_path := fmt.Sprintf("/tmp/code/%s.py", temp_code_name)
-	err := os.MkdirAll("/tmp/code", 0755)
+	untrusted_code_path := fmt.Sprintf("%s/tmp/%s.py", LIB_PATH, temp_code_name)
+	err := os.MkdirAll(path.Dir(untrusted_code_path), 0755)
 	if err != nil {
 		return "", err
 	}

+ 2 - 2
internal/core/runner/python/setup.go

@@ -80,7 +80,7 @@ func InstallDependencies(requirements string) error {
 	}
 
 	runner := runner.TempDirRunner{}
-	return runner.WithTempDir([]string{}, func(root_path string) error {
+	return runner.WithTempDir("/", []string{}, func(root_path string) error {
 		defer os.Remove(root_path)
 		defer os.RemoveAll(root_path)
 		// create a requirements file
@@ -131,7 +131,7 @@ func InstallDependencies(requirements string) error {
 				continue
 			}
 
-			python_dependencies.SetupDependency(package_name, version, fmt.Sprintf("import %s", package_name))
+			python_dependencies.SetupDependency(package_name, version)
 			log.Info("Python dependency installed: %s %s", package_name, version)
 		}
 

+ 2 - 2
internal/core/runner/temp_dir.go

@@ -10,14 +10,14 @@ import (
 
 type TempDirRunner struct{}
 
-func (s *TempDirRunner) WithTempDir(paths []string, closures func(path string) error) error {
+func (s *TempDirRunner) WithTempDir(basedir string, paths []string, closures func(path string) error) error {
 	uuid, err := uuid.NewRandom()
 	if err != nil {
 		return err
 	}
 
 	// create a tmp dir
-	tmp_dir := path.Join("/tmp", "sandbox-"+uuid.String())
+	tmp_dir := path.Join(basedir, "tmp", "sandbox-"+uuid.String())
 	err = os.Mkdir(tmp_dir, 0755)
 	if err != nil {
 		return err

+ 21 - 0
internal/server/server.go

@@ -2,6 +2,7 @@ package server
 
 import (
 	"fmt"
+	"time"
 
 	"github.com/gin-gonic/gin"
 	"github.com/langgenius/dify-sandbox/internal/controller"
@@ -45,6 +46,26 @@ func initDependencies() {
 		log.Panic("failed to install python dependencies: %v", err)
 	}
 	log.Info("python dependencies installed")
+
+	log.Info("initializing python dependencies sandbox...")
+	err = python.PreparePythonDependenciesEnv()
+	if err != nil {
+		log.Panic("failed to initialize python dependencies sandbox: %v", err)
+	}
+	log.Info("python dependencies sandbox initialized")
+
+	// start a ticker to update python dependencies every 30 minutes to keep the sandbox up-to-date
+	go func() {
+		ticker := time.NewTicker(30 * time.Minute)
+		for range ticker.C {
+			log.Info("updating python dependencies...")
+			err := python.InstallDependencies(dependenices.PythonRequirements)
+			if err != nil {
+				log.Error("failed to update python dependencies: %v", err)
+			}
+			log.Info("python dependencies updated")
+		}
+	}()
 }
 
 func Run() {

+ 11 - 0
internal/service/python.go

@@ -62,3 +62,14 @@ func ListPython3Dependencies() *types.DifySandboxResponse {
 		Dependencies: python.ListDependencies(),
 	})
 }
+
+type UpdateDependenciesResponse struct{}
+
+func UpdateDependencies() *types.DifySandboxResponse {
+	err := python.PreparePythonDependenciesEnv()
+	if err != nil {
+		return types.ErrorResponse(-500, err.Error())
+	}
+
+	return types.SuccessResponse(&UpdateDependenciesResponse{})
+}

+ 10 - 0
internal/static/config.go

@@ -3,6 +3,7 @@ package static
 import (
 	"os"
 	"strconv"
+	"strings"
 
 	"github.com/langgenius/dify-sandbox/internal/types"
 	"github.com/langgenius/dify-sandbox/internal/utils/log"
@@ -68,6 +69,15 @@ func InitConfig(path string) error {
 		difySandboxGlobalConfigurations.PythonPath = "/usr/local/bin/python3"
 	}
 
+	python_lib_path := os.Getenv("PYTHON_LIB_PATH")
+	if python_lib_path != "" {
+		difySandboxGlobalConfigurations.PythonLibPaths = strings.Split(python_lib_path, ",")
+	}
+
+	if len(difySandboxGlobalConfigurations.PythonLibPaths) == 0 {
+		difySandboxGlobalConfigurations.PythonLibPaths = DEFAULT_PYTHON_LIB_REQUIREMENTS
+	}
+
 	nodejs_path := os.Getenv("NODEJS_PATH")
 	if nodejs_path != "" {
 		difySandboxGlobalConfigurations.NodejsPath = nodejs_path

+ 17 - 0
internal/static/config_default_amd64.go

@@ -0,0 +1,17 @@
+//go:build linux && amd64
+
+package static
+
+var DEFAULT_PYTHON_LIB_REQUIREMENTS = []string{
+	"/usr/local/lib/python3.10",
+	"/usr/lib/python3.10",
+	"/usr/lib/python3",
+	"/usr/lib/x86_64-linux-gnu/libssl.so.3",
+	"/usr/lib/x86_64-linux-gnu/libcrypto.so.3",
+	"/etc/ssl/certs/ca-certificates.crt",
+	"/etc/nsswitch.conf",
+	"/etc/hosts",
+	"/etc/resolv.conf",
+	"/run/systemd/resolve/stub-resolv.conf",
+	"/run/resolvconf/resolv.conf",
+}

+ 17 - 0
internal/static/config_default_arm64.go

@@ -0,0 +1,17 @@
+//go:build linux && arm64
+
+package static
+
+var DEFAULT_PYTHON_LIB_REQUIREMENTS = []string{
+	"/usr/local/lib/python3.10",
+	"/usr/lib/python3.10",
+	"/usr/lib/python3",
+	"/etc/ssl/certs/ca-certificates.crt",
+	"/etc/nsswitch.conf",
+	"/etc/resolv.conf",
+	"/run/systemd/resolve/stub-resolv.conf",
+	"/run/resolvconf/resolv.conf",
+	"/usr/lib/aarch64-linux-gnu/libssl.so.3",
+	"/usr/lib/aarch64-linux-gnu/libcrypto.so.3",
+	"/etc/hosts",
+}

+ 1 - 0
internal/static/python_syscall/syscalls_arm64.go

@@ -22,6 +22,7 @@ var ALLOW_SYSCALLS = []int{
 	syscall.SYS_TGKILL, syscall.SYS_RT_SIGACTION,
 	syscall.SYS_IOCTL, syscall.SYS_SCHED_YIELD,
 	// time
+	syscall.SYS_EPOLL_CREATE1,
 	syscall.SYS_CLOCK_GETTIME, syscall.SYS_GETTIMEOFDAY, syscall.SYS_NANOSLEEP,
 	syscall.SYS_EPOLL_CTL, syscall.SYS_CLOCK_NANOSLEEP, syscall.SYS_PSELECT6,
 	syscall.SYS_TIMERFD_CREATE, syscall.SYS_TIMERFD_SETTIME, syscall.SYS_TIMERFD_GETTIME,

+ 8 - 7
internal/types/config.go

@@ -6,13 +6,14 @@ type DifySandboxGlobalConfigurations struct {
 		Debug bool   `yaml:"debug"`
 		Key   string `yaml:"key"`
 	} `yaml:"app"`
-	MaxWorkers    int    `yaml:"max_workers"`
-	MaxRequests   int    `yaml:"max_requests"`
-	WorkerTimeout int    `yaml:"worker_timeout"`
-	PythonPath    string `yaml:"python_path"`
-	NodejsPath    string `yaml:"nodejs_path"`
-	EnableNetwork bool   `yaml:"enable_network"`
-	Proxy         struct {
+	MaxWorkers     int      `yaml:"max_workers"`
+	MaxRequests    int      `yaml:"max_requests"`
+	WorkerTimeout  int      `yaml:"worker_timeout"`
+	PythonPath     string   `yaml:"python_path"`
+	PythonLibPaths []string `yaml:"python_lib_path"`
+	NodejsPath     string   `yaml:"nodejs_path"`
+	EnableNetwork  bool     `yaml:"enable_network"`
+	Proxy          struct {
 		Socks5 string `yaml:"socks5"`
 		Https  string `yaml:"https"`
 		Http   string `yaml:"http"`