From: Dmitry Volyntsev Date: Thu, 13 Sep 2018 12:52:17 +0000 (+0300) Subject: Introduced sandboxing mode. X-Git-Tag: 0.2.4~4 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=83c48bbf4ae13855d9ad5575ae38678aeaea38c8;p=njs.git Introduced sandboxing mode. Thanks to David CARLIER. --- diff --git a/njs/njs.c b/njs/njs.c index b62b8f18..3771a81e 100644 --- a/njs/njs.c +++ b/njs/njs.c @@ -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 **start, u_char *end) 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_ptr_t 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_ptr_t external) nvm->external_objects = externals; - nvm->ops = vm->ops; + nvm->options = vm->options; nvm->current = vm->current; diff --git a/njs/njs.h b/njs/njs.h index 3d81b878..923ac60c 100644 --- a/njs/njs.h +++ b/njs/njs.h @@ -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 --git a/njs/njs_builtin.c b/njs/njs_builtin.c index 3de147eb..387d2738 100644 --- a/njs/njs_builtin.c +++ b/njs/njs_builtin.c @@ -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 --git a/njs/njs_generator.c b/njs/njs_generator.c index d33e987b..9721885c 100644 --- a/njs/njs_generator.c +++ b/njs/njs_generator.c @@ -2558,7 +2558,7 @@ njs_generator_temp_index_get(njs_vm_t *vm, njs_parser_t *parser, 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 --git a/njs/njs_module.c b/njs/njs_module.c index ca80cf6b..f6097bec 100644 --- a/njs/njs_module.c +++ b/njs/njs_module.c @@ -74,3 +74,19 @@ const njs_object_init_t njs_require_function_init = { 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 --git a/njs/njs_module.h b/njs/njs_module.h index 58091084..a8b08c96 100644 --- a/njs/njs_module.h +++ b/njs/njs_module.h @@ -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 --git a/njs/njs_parser.c b/njs/njs_parser.c index 7071cba7..77e4f5dd 100644 --- a/njs/njs_parser.c +++ b/njs/njs_parser.c @@ -134,7 +134,7 @@ njs_parser(njs_vm_t *vm, njs_parser_t *parser, njs_parser_t *prev) 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_parser_t *parser, 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 --git a/njs/njs_shell.c b/njs/njs_shell.c index 5b66bdaa..7915b8bf 100644 --- a/njs/njs_shell.c +++ b/njs/njs_shell.c @@ -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 argc, char** argv) "Options:\n" " -v print njs version and exit.\n" " -d print disassembled code.\n" + " -s sandbox mode.\n" " | - run code from a file or stdin.\n"; ret = NXT_DONE; @@ -201,6 +204,10 @@ njs_get_options(njs_opts_t *opts, int argc, char** argv) 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 --git a/njs/njs_time.c b/njs/njs_time.c index 0f624c21..08aa587d 100644 --- a/njs/njs_time.c +++ b/njs/njs_time.c @@ -28,7 +28,7 @@ njs_set_timeout(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, 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 --git a/njs/njs_variable.c b/njs/njs_variable.c index 33ee2c74..5dabd713 100644 --- a/njs/njs_variable.c +++ b/njs/njs_variable.c @@ -123,7 +123,7 @@ njs_variable_add(njs_vm_t *vm, njs_parser_t *parser, njs_variable_type_t type) 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_parser_node_t *node) 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 --git a/njs/njs_vm.h b/njs/njs_vm.h index ee256598..ceb77467 100644 --- a/njs/njs_vm.h +++ b/njs/njs_vm.h @@ -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 --git a/njs/test/njs_expect_test.exp b/njs/test/njs_expect_test.exp index 18878789..12c45d87 100644 --- a/njs/test/njs_expect_test.exp +++ b/njs/test/njs_expect_test.exp @@ -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. -> 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\r 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"