2016-12-09 3 views
1

Ich möchte einige nicht vertrauenswürdigem Code in Knoten auszuführen, die wie folgt aussehen könnte:Kombinieren NodeJS Fibers + VM Sandbox

for (var i = 0; i < 5; i++){ 
    green_led(1); 
    sleep(500); 
    green_led(0); 
    sleep(500); 
} 

Verwendung von Fasern, bekam ich das synchrone Verhalten wie erwartet funktioniert:

var Fiber = require('fibers'); 

function sleep(ms){ 
    var fiber = Fiber.current; 
    setTimeout(function(){ fiber.run(); }, ms); 
    Fiber.yield(); 
} 
function green_led(active){ 
    //... 
} 
Fiber(function(){ 
    for (var i = 0; i < 5; i++){ 
     green_led(1); 
     sleep(500); 
     green_led(0); 
     sleep(500); 
    } 
}).run(); 

Die Schwierigkeit besteht darin, den Code zu sandboxieren. Die Verwendung von Fasern macht es wirklich kompliziert; Ich bin mir nicht sicher, wie ich anfangen soll. Wie kann ich die obige Sandbox mit vm2 bekommen? Zum Beispiel wird im Folgenden offensichtlich nicht:

var code = "\ 
for (var i = 0; i < 5; i++){\ 
    green_led(1);\ 
    sleep(500);\ 
    green_led(0);\ 
    sleep(500);\ 
}\ 
"; 
function sleep(ms){ 
    var fiber = Fiber.current; 
    setTimeout(function(){ fiber.run(); }, ms); 
    Fiber.yield(); 
} 
function green_led(active){ 
    //... 
} 
Fiber(function(){ 
    vm.run(code); 
}).run(); 

(Es wird nicht funktionieren, weil green_led und sleep in der VM nicht sichtbar für den Sandbox-Code sind).

Wie soll das gemacht werden? Entweder ...

  1. Vielleicht sollte alles innerhalb der VM ausgeführt werden, einschließlich Fasern und Implementierung von green_led usw.?
  2. Oder wäre es besser, Code von der VM minimal gehalten zu halten, und stattdessen irgendwie Whitelist/Proxy green_led und sleep? Nicht gerade leicht in der grauen Materie, es ist schwer genug zu verstehen, wie Fibers überhaupt funktioniert!

Antwort

1

Es ist eigentlich ziemlich geradlinig.

var Fiber = require('fibers'); 

const {VM} = require('vm2'); 
const vm = new VM({ 
    sandbox: { 
     green_led: green_led, 
     sleep: sleep 
    } 
}); 

function sleep(ms){ 
    var fiber = Fiber.current; 
    setTimeout(function(){ fiber.run(); }, ms); 
    Fiber.yield(); 
} 
function green_led(active){ 
    //... 
} 

vm.run(
    `Fiber(function(){ 
     for (var i = 0; i < 5; i++){ 
      green_led(1); 
      sleep(500); 
      green_led(0); 
      sleep(500); 
     } 
    }).run()` 
); 

Der obige Ansatz verläuft in einem Verweis auf Fiber und die anderen Funktionen und sleepgreen_led über den Sandkasten-Objekt. Dies könnte auf andere Arten geschehen. Zum Beispiel sleep und green_led konnte innerhalb der Zeichenfolge zu vm.run() weitergegeben definiert werden, und die vm konnte sich includefibers wie so:

const {NodeVM} = require('vm2'); 
var vm = new NodeVM({ 
    require: { 
     external: true, 
    } 
}); 
vm.run(
    ` 
    var Fiber = require("fibers"); 
    function sleep(ms){ 
     var fiber = Fiber.current; 
     setTimeout(function(){ fiber.run(); }, ms); 
     Fiber.yield(); 
    } 
    function green_led(active){ 
     //... 
    } 
    Fiber(function(){ 
     for (var i = 0; i < 5; i++){ 
      green_led(1); 
      sleep(500); 
      green_led(0); 
      sleep(500); 
     } 
    }).run()` 
); 

Per the documentation, den Unterschied zwischen VM und NodeVM bemerken. Von den beiden oben genannten Methoden könnte nur die erste die Timeout-Funktion nutzen. Auch ist die zweite Methode nicht immun gegen while (true) {} usw.

Verwandte Themen