Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ DifySandbox currently only supports Linux, as it's designed for docker container
1. Clone the repository using `git clone https://github.com/langgenius/dify-sandbox` and navigate to the project directory.
2. Run ./install.sh to install the necessary dependencies.
3. Run ./build/build_[amd64|arm64].sh to build the sandbox binary.
4. Run ./main to start the server.
4. Run ./sandbox_userctl.sh to create sandbox-related users, it needs to be executed by the root user
5. Run ./main to start the server.

If you want to debug the server, firstly use build script to build the sandbox library binaries, then debug as you want with your IDE.

Expand Down
24 changes: 20 additions & 4 deletions cmd/lib/nodejs/main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
package main

import "github.com/langgenius/dify-sandbox/internal/core/lib/nodejs"
import (
"fmt"
"os"

"github.com/langgenius/dify-sandbox/internal/core/lib"
"github.com/langgenius/dify-sandbox/internal/core/lib/nodejs"
)

/*
#include <stdint.h>
*/
import "C"

//export DifySeccomp
func DifySeccomp(uid int, gid int, enable_network bool) {
if err := nodejs.InitSeccomp(uid, gid, enable_network); err != nil {
panic(err)
func DifySeccomp(uid int, gid int, enable_network bool) C.int {
err := nodejs.InitSeccomp(uid, gid, enable_network)
if err != nil {
fmt.Fprintf(os.Stderr, "nodejs DifySeccomp error: %v\n", err)
if coder, ok := err.(lib.ErrorCoder); ok {
return C.int(coder.GetCode())
}
return C.int(lib.ERR_UNKNOWN)
}
return C.int(lib.SUCCESS)
}

func main() {}
20 changes: 17 additions & 3 deletions cmd/lib/python/main.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
package main

import (
"fmt"
"os"

"github.com/langgenius/dify-sandbox/internal/core/lib"
"github.com/langgenius/dify-sandbox/internal/core/lib/python"
)

/*
#include <stdint.h>
*/
import "C"

//export DifySeccomp
func DifySeccomp(uid int, gid int, enable_network bool) {
if err := python.InitSeccomp(uid, gid, enable_network); err != nil {
panic(err)
func DifySeccomp(uid int, gid int, enable_network bool) C.int {
err := python.InitSeccomp(uid, gid, enable_network)
if err != nil {
fmt.Fprintf(os.Stderr, "python DifySeccomp error: %v\n", err)
if coder, ok := err.(lib.ErrorCoder); ok {
return C.int(coder.GetCode())
}
return C.int(lib.ERR_UNKNOWN)
}
return C.int(lib.SUCCESS)
}

func main() {}
13 changes: 13 additions & 0 deletions internal/core/lib/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package lib

const (
SUCCESS = 0
ERR_CHROOT = 1
ERR_CHDIR = 2
ERR_SETNONEWPRIVS = 3
ERR_SECCOMP = 4
ERR_SETUID = 5
ERR_SETGID = 6
ERR_SETGROPS = 7
ERR_UNKNOWN = 99
)
82 changes: 82 additions & 0 deletions internal/core/lib/error_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package lib

import (
"fmt"
)

type ErrorCoder interface {
GetCode() int
}

type BaseError struct {
Err error
Code int
}

func (e *BaseError) Error() string {
return fmt.Sprintf("error code %d: %v", e.Code, e.Err)
}

func (e *BaseError) Unwrap() error {
return e.Err
}

func (e *BaseError) GetCode() int {
return e.Code
}

type ChrootError struct {
BaseError
}

func (e *ChrootError) Error() string {
return fmt.Sprintf("chroot failed: %v", e.Err)
}

type ChdirError struct {
BaseError
}

func (e *ChdirError) Error() string {
return fmt.Sprintf("chdir failed: %v", e.Err)
}

type SetNoNewPrivsError struct {
BaseError
}

func (e *SetNoNewPrivsError) Error() string {
return fmt.Sprintf("set no new privs failed: %v", e.Err)
}

type SetuidError struct {
BaseError
}

func (e *SetuidError) Error() string {
return fmt.Sprintf("setuid failed: %v", e.Err)
}

type SetgidError struct {
BaseError
}

func (e *SetgidError) Error() string {
return fmt.Sprintf("setgid failed: %v", e.Err)
}

type SeccompError struct {
BaseError
}

func (e *SeccompError) Error() string {
return fmt.Sprintf("seccomp failed: %v", e.Err)
}

type SetgroupsError struct {
BaseError
}

func (e *SetgroupsError) Error() string {
return fmt.Sprintf("setgroups failed: %v", e.Err)
}
52 changes: 45 additions & 7 deletions internal/core/lib/nodejs/add_seccomp.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,32 @@ import (
func InitSeccomp(uid int, gid int, enable_network bool) error {
err := syscall.Chroot(".")
if err != nil {
return err
return &lib.ChrootError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_CHROOT,
},
}
}
err = syscall.Chdir("/")
if err != nil {
return err
return &lib.ChdirError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_CHDIR,
},
}
}

lib.SetNoNewPrivs()
err = lib.SetNoNewPrivs()
if err != nil {
return &lib.SetNoNewPrivsError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_SETNONEWPRIVS,
},
}
}

allowed_syscalls := []int{}
allowed_not_kill_syscalls := []int{}
Expand All @@ -51,24 +69,44 @@ func InitSeccomp(uid int, gid int, enable_network bool) error {

err = lib.Seccomp(allowed_syscalls, allowed_not_kill_syscalls)
if err != nil {
return err
return &lib.SeccompError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_SECCOMP,
},
}
}

err = syscall.Setgroups([]int{})
if err != nil {
return err
return &lib.SetgroupsError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_SETGROPS,
},
}
}

// setgid
err = syscall.Setgid(gid)
if err != nil {
return err
return &lib.SetgidError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_SETGID,
},
}
}

// setuid
err = syscall.Setuid(uid)
if err != nil {
return err
return &lib.SetuidError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_SETUID,
},
}
}

return nil
Expand Down
52 changes: 45 additions & 7 deletions internal/core/lib/python/add_seccomp.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,32 @@ import (
func InitSeccomp(uid int, gid int, enable_network bool) error {
err := syscall.Chroot(".")
if err != nil {
return err
return &lib.ChrootError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_CHROOT,
},
}
}
err = syscall.Chdir("/")
if err != nil {
return err
return &lib.ChdirError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_CHDIR,
},
}
}

lib.SetNoNewPrivs()
err = lib.SetNoNewPrivs()
if err != nil {
return &lib.SetNoNewPrivsError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_SETNONEWPRIVS,
},
}
}

allowed_syscalls := []int{}
allowed_not_kill_syscalls := []int{}
Expand All @@ -50,24 +68,44 @@ func InitSeccomp(uid int, gid int, enable_network bool) error {

err = lib.Seccomp(allowed_syscalls, allowed_not_kill_syscalls)
if err != nil {
return err
return &lib.SeccompError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_SECCOMP,
},
}
}

err = syscall.Setgroups([]int{})
if err != nil {
return err
return &lib.SetgroupsError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_SETGROPS,
},
}
}

// setgid
err = syscall.Setgid(gid)
if err != nil {
return err
return &lib.SetgidError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_SETGID,
},
}
}

// setuid
err = syscall.Setuid(uid)
if err != nil {
return err
return &lib.SetuidError{
BaseError: lib.BaseError{
Err: err,
Code: lib.ERR_SETUID,
},
}
}

return nil
Expand Down
7 changes: 6 additions & 1 deletion internal/core/runner/nodejs/nodejs.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ extern const char *_GoStringPtr(_GoString_ s);
/* Start of preamble from import "C" comments. */


#line 11 "main.go"

#include <stdint.h>

#line 1 "cgo-generated-wrapper"


/* End of preamble from import "C" comments. */
Expand Down Expand Up @@ -82,7 +87,7 @@ typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
extern "C" {
#endif

extern void DifySeccomp(GoInt uid, GoInt gid, GoUint8 enable_network);
extern int DifySeccomp(GoInt uid, GoInt gid, GoUint8 enable_network);

#ifdef __cplusplus
}
Expand Down
20 changes: 18 additions & 2 deletions internal/core/runner/nodejs/prescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,30 @@ const fs = require('fs')

const koffi = require('koffi')
const lib = koffi.load('./var/sandbox/sandbox-nodejs/nodejs.so')
const difySeccomp = lib.func('void DifySeccomp(int, int, bool)')
const difySeccomp = lib.func('int DifySeccomp(int, int, bool)')

const uid = parseInt(argv[2])
const gid = parseInt(argv[3])

const options = JSON.parse(argv[4])

difySeccomp(uid, gid, options['enable_network'])
const ret = difySeccomp(uid, gid, options['enable_network'])

if (ret !== 0) {
const errorMessages = {
1: "Chroot failed",
2: "Chdir failed",
3: "Set no new privs failed",
4: "Seccomp failed",
5: "Setuid failed",
6: "Setgid failed",
7: "Setgroups failed",
99: "Unknown error",
}
const errorMsg = errorMessages[ret] || `Unknown error code: ${ret}`
console.error(`DifySeccomp failed: ${errorMsg}`)
process.exit(-1)
}

const code = fs.readFileSync(3, 'utf8')
eval(code)
Loading