[njs] Introduced sandboxing mode.
Dmitry Volyntsev
xeioex at nginx.com
Thu Sep 13 14:54:26 UTC 2018
details: http://hg.nginx.org/njs/rev/a92ae4986bc0
branches:
changeset: 603:a92ae4986bc0
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Thu Sep 13 15:52:17 2018 +0300
description:
Introduced sandboxing mode.
Thanks to David CARLIER.
diffstat:
njs/njs.c | 15 ++++++---------
njs/njs.h | 1 +
njs/njs_builtin.c | 4 ++++
njs/njs_generator.c | 2 +-
njs/njs_module.c | 16 ++++++++++++++++
njs/njs_module.h | 1 +
njs/njs_parser.c | 4 ++--
njs/njs_shell.c | 7 +++++++
njs/njs_time.c | 2 +-
njs/njs_variable.c | 4 ++--
njs/njs_vm.h | 4 +---
njs/test/njs_expect_test.exp | 37 +++++++++++++++++++++++++++++++++++--
12 files changed, 77 insertions(+), 20 deletions(-)
diffs (307 lines):
diff -r c2cddf3b97b7 -r a92ae4986bc0 njs/njs.c
--- a/njs/njs.c Tue Sep 11 15:35:27 2018 +0300
+++ b/njs/njs.c Thu Sep 13 15:52:17 2018 +0300
@@ -110,6 +110,8 @@ njs_vm_create(njs_vm_opt_t *options)
return NULL;
}
+ vm->options = *options;
+
if (options->shared != NULL) {
vm->shared = options->shared;
@@ -160,15 +162,11 @@ njs_vm_create(njs_vm_opt_t *options)
nxt_lvlhsh_init(&vm->externals_hash);
nxt_lvlhsh_init(&vm->external_prototypes_hash);
- vm->ops = options->ops;
-
vm->trace.level = NXT_LEVEL_TRACE;
vm->trace.size = 2048;
vm->trace.handler = njs_parser_trace_handler;
vm->trace.data = vm;
- vm->trailer = options->trailer;
-
if (options->backtrace) {
debug = nxt_array_create(4, sizeof(njs_function_debug_t),
&njs_array_mem_proto,
@@ -180,8 +178,7 @@ njs_vm_create(njs_vm_opt_t *options)
vm->debug = debug;
}
- vm->accumulative = options->accumulative;
- if (vm->accumulative) {
+ if (options->accumulative) {
ret = njs_vm_init(vm);
if (nxt_slow_path(ret != NXT_OK)) {
return NULL;
@@ -232,7 +229,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **st
return NJS_ERROR;
}
- if (vm->parser != NULL && !vm->accumulative) {
+ if (vm->parser != NULL && !vm->options.accumulative) {
return NJS_ERROR;
}
@@ -307,7 +304,7 @@ njs_vm_clone(njs_vm_t *vm, njs_external_
nxt_thread_log_debug("CLONE:");
- if (vm->accumulative) {
+ if (vm->options.accumulative) {
return NULL;
}
@@ -347,7 +344,7 @@ njs_vm_clone(njs_vm_t *vm, njs_external_
nvm->external_objects = externals;
- nvm->ops = vm->ops;
+ nvm->options = vm->options;
nvm->current = vm->current;
diff -r c2cddf3b97b7 -r a92ae4986bc0 njs/njs.h
--- a/njs/njs.h Tue Sep 11 15:35:27 2018 +0300
+++ b/njs/njs.h Thu Sep 13 15:52:17 2018 +0300
@@ -145,6 +145,7 @@ typedef struct {
uint8_t trailer; /* 1 bit */
uint8_t accumulative; /* 1 bit */
uint8_t backtrace; /* 1 bit */
+ uint8_t sandbox; /* 1 bit */
} njs_vm_opt_t;
diff -r c2cddf3b97b7 -r a92ae4986bc0 njs/njs_builtin.c
--- a/njs/njs_builtin.c Tue Sep 11 15:35:27 2018 +0300
+++ b/njs/njs_builtin.c Thu Sep 13 15:52:17 2018 +0300
@@ -256,6 +256,10 @@ njs_builtin_objects_create(njs_vm_t *vm)
lhq.pool = vm->mem_cache_pool;
for (i = NJS_MODULE_FS; i < NJS_MODULE_MAX; i++) {
+ if (vm->options.sandbox && !njs_sandbox_module(i)) {
+ continue;
+ }
+
module = nxt_mem_cache_zalloc(vm->mem_cache_pool, sizeof(njs_module_t));
if (nxt_slow_path(module == NULL)) {
return NJS_ERROR;
diff -r c2cddf3b97b7 -r a92ae4986bc0 njs/njs_generator.c
--- a/njs/njs_generator.c Tue Sep 11 15:35:27 2018 +0300
+++ b/njs/njs_generator.c Thu Sep 13 15:52:17 2018 +0300
@@ -2558,7 +2558,7 @@ njs_generator_temp_index_get(njs_vm_t *v
scope = scope->parent;
}
- if (vm->accumulative && scope->type == NJS_SCOPE_GLOBAL) {
+ if (vm->options.accumulative && scope->type == NJS_SCOPE_GLOBAL) {
/*
* When non-clonable VM runs in accumulative mode
* all global variables are allocated in absolute scope
diff -r c2cddf3b97b7 -r a92ae4986bc0 njs/njs_module.c
--- a/njs/njs_module.c Tue Sep 11 15:35:27 2018 +0300
+++ b/njs/njs_module.c Thu Sep 13 15:52:17 2018 +0300
@@ -74,3 +74,19 @@ const njs_object_init_t njs_require_fun
NULL,
0,
};
+
+
+nxt_bool_t
+njs_sandbox_module(enum njs_module_e module)
+{
+ switch (module) {
+ case NJS_MODULE_CRYPTO:
+ return 1;
+
+ case NJS_MODULE_FS:
+ default:
+ break;
+ }
+
+ return 0;
+}
diff -r c2cddf3b97b7 -r a92ae4986bc0 njs/njs_module.h
--- a/njs/njs_module.h Tue Sep 11 15:35:27 2018 +0300
+++ b/njs/njs_module.h Thu Sep 13 15:52:17 2018 +0300
@@ -15,6 +15,7 @@ typedef struct {
njs_ret_t njs_module_require(njs_vm_t *vm, njs_value_t *args,
nxt_uint_t nargs, njs_index_t unused);
+nxt_bool_t njs_sandbox_module(enum njs_module_e module);
extern const nxt_lvlhsh_proto_t njs_modules_hash_proto;
diff -r c2cddf3b97b7 -r a92ae4986bc0 njs/njs_parser.c
--- a/njs/njs_parser.c Tue Sep 11 15:35:27 2018 +0300
+++ b/njs/njs_parser.c Thu Sep 13 15:52:17 2018 +0300
@@ -134,7 +134,7 @@ njs_parser(njs_vm_t *vm, njs_parser_t *p
return NULL;
}
- if (token == NJS_TOKEN_CLOSE_BRACE && vm->trailer) {
+ if (token == NJS_TOKEN_CLOSE_BRACE && vm->options.trailer) {
parser->lexer->start--;
break;
}
@@ -351,7 +351,7 @@ njs_parser_statement(njs_vm_t *vm, njs_p
return njs_parser_block_statement(vm, parser);
case NJS_TOKEN_CLOSE_BRACE:
- if (vm->trailer) {
+ if (vm->options.trailer) {
parser->node = NULL;
nxt_thread_log_debug("BLOCK END");
return token;
diff -r c2cddf3b97b7 -r a92ae4986bc0 njs/njs_shell.c
--- a/njs/njs_shell.c Tue Sep 11 15:35:27 2018 +0300
+++ b/njs/njs_shell.c Thu Sep 13 15:52:17 2018 +0300
@@ -31,6 +31,7 @@ typedef struct {
nxt_int_t version;
nxt_int_t disassemble;
nxt_int_t interactive;
+ nxt_int_t sandbox;
} njs_opts_t;
@@ -146,6 +147,7 @@ main(int argc, char **argv)
vm_options.accumulative = 1;
vm_options.backtrace = 1;
+ vm_options.sandbox = opts.sandbox;
if (opts.interactive) {
ret = njs_interactive_shell(&opts, &vm_options);
@@ -170,6 +172,7 @@ njs_get_options(njs_opts_t *opts, int ar
"Options:\n"
" -v print njs version and exit.\n"
" -d print disassembled code.\n"
+ " -s sandbox mode.\n"
" <filename> | - run code from a file or stdin.\n";
ret = NXT_DONE;
@@ -201,6 +204,10 @@ njs_get_options(njs_opts_t *opts, int ar
opts->version = 1;
break;
+ case 's':
+ opts->sandbox = 1;
+ break;
+
default:
fprintf(stderr, "Unknown argument: \"%s\" "
"try \"%s -h\" for available options\n", argv[i], argv[0]);
diff -r c2cddf3b97b7 -r a92ae4986bc0 njs/njs_time.c
--- a/njs/njs_time.c Tue Sep 11 15:35:27 2018 +0300
+++ b/njs/njs_time.c Thu Sep 13 15:52:17 2018 +0300
@@ -28,7 +28,7 @@ njs_set_timeout(njs_vm_t *vm, njs_value_
return NJS_ERROR;
}
- ops = vm->ops;
+ ops = vm->options.ops;
if (nxt_slow_path(ops == NULL)) {
njs_internal_error(vm, "not supported by host environment");
return NJS_ERROR;
diff -r c2cddf3b97b7 -r a92ae4986bc0 njs/njs_variable.c
--- a/njs/njs_variable.c Tue Sep 11 15:35:27 2018 +0300
+++ b/njs/njs_variable.c Thu Sep 13 15:52:17 2018 +0300
@@ -123,7 +123,7 @@ njs_variable_add(njs_vm_t *vm, njs_parse
return var;
}
- lhq.replace = vm->accumulative;
+ lhq.replace = vm->options.accumulative;
lhq.value = var;
lhq.pool = vm->mem_cache_pool;
@@ -389,7 +389,7 @@ njs_variable_get(njs_vm_t *vm, njs_parse
goto not_found;
}
- if (vm->accumulative && vs.scope->type == NJS_SCOPE_GLOBAL) {
+ if (vm->options.accumulative && vs.scope->type == NJS_SCOPE_GLOBAL) {
/*
* When non-clonable VM runs in accumulative mode all
* global variables should be allocated in absolute scope
diff -r c2cddf3b97b7 -r a92ae4986bc0 njs/njs_vm.h
--- a/njs/njs_vm.h Tue Sep 11 15:35:27 2018 +0300
+++ b/njs/njs_vm.h Thu Sep 13 15:52:17 2018 +0300
@@ -1036,7 +1036,7 @@ struct njs_vm_s {
nxt_lvlhsh_t events_hash;
nxt_queue_t posted_events;
- njs_vm_ops_t *ops;
+ njs_vm_opt_t options;
/*
* The prototypes and constructors arrays must be together because
@@ -1073,8 +1073,6 @@ struct njs_vm_s {
nxt_array_t *backtrace;
njs_trap_t trap:8;
- uint8_t trailer; /* 1 bit */
- uint8_t accumulative; /* 1 bit */
};
diff -r c2cddf3b97b7 -r a92ae4986bc0 njs/test/njs_expect_test.exp
--- a/njs/test/njs_expect_test.exp Tue Sep 11 15:35:27 2018 +0300
+++ b/njs/test/njs_expect_test.exp Thu Sep 13 15:52:17 2018 +0300
@@ -3,8 +3,15 @@
# Copyright (C) NGINX, Inc.
#
-proc njs_test {body} {
- spawn -nottycopy njs
+proc njs_test {body {opts ""}} {
+
+ if {$opts eq ""} {
+ spawn -nottycopy njs
+
+ } else {
+ spawn -nottycopy njs $opts
+ }
+
expect -re "interactive njs \\d+\.\\d+\.\\d+\r\n\r"
expect "v.<Tab> -> the properties and prototype methods of v.\r
type console.help() for more information\r
@@ -23,6 +30,12 @@ type console.help() for more information
expect eof
}
+proc njs_run {opts output} {
+ spawn -nottycopy njs $opts
+ expect -re $output
+ expect eof
+}
+
njs_test {
{"njs.version\r\n"
"njs.version\r\n\*\.\*\.\*"}
@@ -490,3 +503,23 @@ njs_test {
{"fs.readFileSync('njs_test_file2')\r\n"
"'ABCABC'\r\n>> "}
}
+
+# CLI OPTIONS
+
+# version
+
+njs_run "-v" "\\d+\.\\d+\.\\d+"
+
+# disassemble
+
+njs_test {
+ {"1+1\r\n"
+ "00000 ADD*\r\n00040 STOP*\r\n\r\n2"}
+} "-d"
+
+# sandboxing
+
+njs_test {
+ {"var fs = require('fs')\r\n"
+ "Error: Cannot find module 'fs'\r\n"}
+} "-s"
More information about the nginx-devel
mailing list