diff --git a/README.md b/README.md index e6ca47d..914ea57 100644 --- a/README.md +++ b/README.md @@ -90,10 +90,15 @@ A demostration is available in the `demo` directory. In order to get the demostration running for every one, we create the directory `/opt/sandbox-test`. ```bash +git clone https://github.com/t123yh/simple-sandbox.git +npm install +npm run build sudo mkdir /opt/sandbox-test sudo chown $(whoami) /opt/sandbox-test mkdir /opt/sandbox-test/rootfs /opt/sandbox-test/binary /opt/sandbox-test/working -curl -L https://nl.alpinelinux.org/alpine/v3.5/releases/x86_64/alpine-minirootfs-3.5.2-x86_64.tar.gz | tar -xzvf - -C /opt/sandbox-test/rootfs +curl -L https://dl-cdn.alpinelinux.org/alpine/v3.12/releases/x86_64/alpine-minirootfs-3.12.3-x86_64.tar.gz | tar -xzvf - -C /opt/sandbox-test/rootfs +sudo chroot /sandbox-test/rootfs /bin/sh +adduser sandbox +exit +sudo node demo/demo ``` - -**(to be continued)** diff --git a/package.json b/package.json index 0dd44c5..b16ce3c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "simple-sandbox", - "version": "0.3.20", + "version": "0.3.21", "description": "A simple sandbox for Node.js using Linux namespaces and cgroup.", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -22,13 +22,13 @@ "randomstring": "^1.1.5" }, "devDependencies": { - "@types/node": "^14.14.6", - "typescript": "^4.0.5" + "@types/node": "^14.14.19", + "typescript": "^4.1.3" }, "scripts": { "install": "cmake-js compile", - "build": "tsc -p ./src", - "build:watch": "tsc -w -p ./src" + "build": "tsc", + "build:watch": "tsc -w" }, "files": [ "CMakeLists.txt", diff --git a/src/index.ts b/src/index.ts index 985628e..f96e8bf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,7 +14,18 @@ if (!existsSync('/sys/fs/cgroup/memory/memory.memsw.usage_in_bytes')) { const MAX_RETRY_TIMES = 20; export function startSandbox(parameter: SandboxParameter): SandboxProcess { const doStart = () => { - const actualParameter = Object.assign({}, parameter); + const actualParameter = Object.assign({ + time: -1, + memory: -1, + process: -1, + hostname: '', + mounts: [], + redirectBeforeChroot: false, + mountProc: false, + parameters: [], + environments: Object.entries(process.env).map(([key, value]) => key + '=' + value), + workingDirectory: '/' + }, parameter); actualParameter.cgroup = path.join(actualParameter.cgroup, randomString.generate(9)); const startResult: { pid: number; execParam: ArrayBuffer } = nativeAddon.startSandbox(actualParameter); return new SandboxProcess(actualParameter, startResult.pid, startResult.execParam); diff --git a/src/interfaces.ts b/src/interfaces.ts index 586098e..3705da7 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -11,13 +11,13 @@ export interface MountInfo { export interface SandboxParameter { // Time limit, in milliseconds. -1 for no limit. - time: number; + time?: number; // Memory limit, in bytes. -1 for no limit. - memory: number; + memory?: number; // The maximum child process count that may be created by the executable. Typically less than 10. -1 for no limit. - process: number; + process?: number; // This is location of the root filesystem of the sandbox on your machine, // that will be mounted readonly when executing the sandboxed program as /. @@ -29,9 +29,9 @@ export interface SandboxParameter { chroot: string; // The hostname inside the sandbox, by default equals to the hostname outside. - hostname: string; + hostname?: string; - mounts: MountInfo[]; + mounts?: MountInfo[]; // Whether to redirect the stdio before chroot (and setuid). // True indicates that stdio should be redirected before chrooting. @@ -39,14 +39,14 @@ export interface SandboxParameter { // and may be anything like `/dev/stdout` to write output to the console. // False indicates that stdio should be redirected after chrooting. // In this way, the path is relative to the `/sandbox/working` directory, and the permission will be checked when creating the output files. - redirectBeforeChroot: boolean; + redirectBeforeChroot?: boolean; // Whether to mount `/proc` inside the sandbox. // The sandbox is under a PID namespace and the sandboxed program will see itself as PID 1. // The mounted `/proc` is corresponding to the PID namespace. // Some applications (like Node.js) requires `/proc` mounted in order to function correctly. // Some applications will also need `/sys` and `/dev`. Please bind mount them to your rootfs at your own risk. - mountProc: boolean; + mountProc?: boolean; // The executable file to be run. // You can specify a executable file in your binary directory. Note that the path is relative to the inside of the sandbox. @@ -61,9 +61,9 @@ export interface SandboxParameter { // or else it will be relative to the working directory of the sandbox (relative path specified), // or absolute path in the sandbox (absolute path specified). // If it is not specified, the stdio will be redirected to /dev/null. - stdin?: string | Number; - stdout?: string | Number; - stderr?: string | Number; + stdin?: string | Number | null; + stdout?: string | Number | null; + stderr?: string | Number | null; // The UID and GID to run the sandboxed program with. // Please make sure that this user have the read permission to the chroot and binary directory, @@ -90,7 +90,7 @@ export interface SandboxParameter { environments?: string[]; // This directory will be changed into (`chdir`) before running the binary. - workingDirectory: string; + workingDirectory?: string; // If set, a `setrlimit` will be run to limit the stack size. // -1 indicates no limit. diff --git a/src/tsconfig.json b/src/tsconfig.json deleted file mode 100644 index 6d3ab6a..0000000 --- a/src/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "removeComments": true, - "preserveConstEnums": true, - "sourceMap": true, - "outDir": "../lib", - "target": "es2017", - "declaration": true, - "lib": [ - "dom", - "es2015", - "es2016" - ] - } -} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..158717b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "commonjs", + "removeComments": true, + "preserveConstEnums": true, + "sourceMap": true, + "outDir": "lib", + "target": "esnext", + "declaration": true + }, + "include": [ + "src" + ] +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index a5df1ba..7685aaa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^14.14.6": - version "14.14.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.6.tgz#146d3da57b3c636cc0d1769396ce1cfa8991147f" - integrity sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw== +"@types/node@^14.14.19": + version "14.14.19" + resolved "https://registry.npm.taobao.org/@types/node/download/@types/node-14.14.19.tgz?cache=0&sync_timestamp=1609521920051&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-14.14.19.tgz#5135176a8330b88ece4e9ab1fdcfc0a545b4bab4" + integrity sha1-UTUXaoMwuI7OTpqx/c/ApUW0urQ= ajv@^6.5.5: version "6.11.0" @@ -854,10 +854,10 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -typescript@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389" - integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ== +typescript@^4.1.3: + version "4.1.3" + resolved "https://registry.npm.taobao.org/typescript/download/typescript-4.1.3.tgz?cache=0&sync_timestamp=1609570528561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftypescript%2Fdownload%2Ftypescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" + integrity sha1-UZ1YK9lMugz4k0x9joRn5HP1O7c= universalify@^0.1.0: version "0.1.2"