blueloveTH 6 дней назад
Родитель
Сommit
af9dbb39d7

+ 1 - 0
include/pocketpy/interpreter/vm.h

@@ -50,6 +50,7 @@ typedef struct VM {
     py_GlobalRef main;      // __main__ module
 
     py_Callbacks callbacks;
+    py_Capabilities capabilities;
 
     py_TValue last_retval;
     py_TValue unhandled_exc;

+ 1 - 4
include/pocketpy/sandbox.h

@@ -13,10 +13,7 @@ typedef struct py_Capabilities {
     bool (*os_system)(const char* command);
     bool (*os_remove)(const char* path);
     // stdc
-    bool stdc_write;    // memset, write_bytes, ...
-    bool stdc_read;     // memcmp, read_bytes, ...
-    bool stdc_malloc;   // malloc
-    bool stdc_free;     // free
+    bool stdc;
 } py_Capabilities;
 
 /// Setup the capabilities for the current VM.

+ 3 - 1
src/interpreter/vm.c

@@ -93,6 +93,8 @@ void VM__ctor(VM* self) {
     self->callbacks.flush = pk_default_flush;
     self->callbacks.getchr = pk_default_getchr;
 
+    memset(&self->capabilities, 0, sizeof(py_Capabilities));
+
     self->last_retval = *py_NIL();
     self->unhandled_exc = *py_NIL();
 
@@ -195,7 +197,7 @@ void VM__ctor(VM* self) {
     INJECT_BUILTIN_EXC(SyntaxError, tp_Exception);
     INJECT_BUILTIN_EXC(RecursionError, tp_Exception);
     INJECT_BUILTIN_EXC(OSError, tp_Exception);
-    INJECT_BUILTIN_EXC(PermissionError, tp_OSError);
+    INJECT_BUILTIN_EXC(PermissionError, tp_Exception);
     INJECT_BUILTIN_EXC(NotImplementedError, tp_Exception);
     INJECT_BUILTIN_EXC(TypeError, tp_Exception);
     INJECT_BUILTIN_EXC(IndexError, tp_Exception);

+ 30 - 0
src/modules/os.c

@@ -38,6 +38,12 @@ static bool os_chdir(int argc, py_Ref argv) {
     PY_CHECK_ARGC(1);
     PY_CHECK_ARG_TYPE(0, tp_str);
     const char* path = py_tostr(py_arg(0));
+
+    py_Capabilities* caps = py_capabilities();
+    if(!caps->os_chdir || !caps->os_chdir(path)) {
+        return py_exception(tp_PermissionError, "disallowed capability");
+    }
+
     int code = platform_chdir(path);
     if(code != 0) {
         const char* msg = strerror(errno);
@@ -49,6 +55,12 @@ static bool os_chdir(int argc, py_Ref argv) {
 
 static bool os_getcwd(int argc, py_Ref argv) {
     PY_CHECK_ARGC(0);
+
+    py_Capabilities* caps = py_capabilities();
+    if(!caps->os_getcwd || !caps->os_getcwd()) {
+        return py_exception(tp_PermissionError, "disallowed capability");
+    }
+
     char buf[1024];
     if(!platform_getcwd(buf, sizeof(buf))) return OSError("getcwd() failed");
     py_newstr(py_retval(), buf);
@@ -60,6 +72,12 @@ static bool os_system(int argc, py_Ref argv) {
     PY_CHECK_ARG_TYPE(0, tp_str);
 #if PK_IS_DESKTOP_PLATFORM
     const char* cmd = py_tostr(py_arg(0));
+
+    py_Capabilities* caps = py_capabilities();
+    if(!caps->os_system || !caps->os_system(cmd)) {
+        return py_exception(tp_PermissionError, "disallowed capability");
+    }
+
     int code = system(cmd);
     py_newint(py_retval(), code);
     return true;
@@ -72,6 +90,12 @@ static bool os_remove(int argc, py_Ref argv) {
     PY_CHECK_ARGC(1);
     PY_CHECK_ARG_TYPE(0, tp_str);
     const char* path = py_tostr(py_arg(0));
+
+    py_Capabilities* caps = py_capabilities();
+    if(!caps->os_remove || !caps->os_remove(path)) {
+        return py_exception(tp_PermissionError, "disallowed capability");
+    }
+
     int code = remove(path);
     if(code != 0) {
         const char* msg = strerror(errno);
@@ -112,6 +136,12 @@ static bool io_FileIO__new__(int argc, py_Ref argv) {
     io_FileIO* ud = py_newobject(py_retval(), cls, 0, sizeof(io_FileIO));
     ud->path = py_tostr(py_arg(1));
     ud->mode = py_tostr(py_arg(2));
+
+    py_Capabilities* caps = py_capabilities();
+    if(!caps->file_open || !caps->file_open(ud->path, ud->mode)) {
+        return py_exception(tp_PermissionError, "disallowed capability");
+    }
+
     ud->file = fopen(ud->path, ud->mode);
     if(ud->file == NULL) {
         const char* msg = strerror(errno);

+ 27 - 0
src/modules/stdc.c

@@ -2,8 +2,17 @@
 #include "pocketpy/interpreter/vm.h"
 #include <string.h>
 
+
+static bool check_stdc_cap() {
+    py_Capabilities* caps = py_capabilities();
+    if(caps->stdc) return true;
+    return py_exception(tp_PermissionError, "disallowed capability");
+}
+
+
 #define DEF_BUILTIN_MEMORY_T(Char_, char_, tp_int_, py_newint_, py_toint_, py_i64_)                \
     static bool stdc_##Char_##__new__(int argc, py_Ref argv) {                                     \
+        if(!check_stdc_cap()) return false;                                                        \
         char_* ud = py_newobject(py_retval(), tp_stdc_##Char_, 0, sizeof(char_));                  \
         if(argc == 2) {                                                                            \
             PY_CHECK_ARG_TYPE(1, tp_int_);                                                         \
@@ -14,12 +23,14 @@
         return true;                                                                               \
     }                                                                                              \
     static bool stdc_##Char_##__get_value(int argc, py_Ref argv) {                                 \
+        if(!check_stdc_cap()) return false;                                                        \
         PY_CHECK_ARGC(1);                                                                          \
         char_* ud = py_touserdata(argv);                                                           \
         py_newint_(py_retval(), (py_i64_)(*ud));                                                   \
         return true;                                                                               \
     }                                                                                              \
     static bool stdc_##Char_##__set_value(int argc, py_Ref argv) {                                 \
+        if(!check_stdc_cap()) return false;                                                        \
         PY_CHECK_ARGC(2);                                                                          \
         char_* ud = py_touserdata(argv);                                                           \
         PY_CHECK_ARG_TYPE(1, tp_int_);                                                             \
@@ -28,6 +39,7 @@
         return true;                                                                               \
     }                                                                                              \
     static bool stdc_##Char_##__read_STATIC(int argc, py_Ref argv) {                               \
+        if(!check_stdc_cap()) return false;                                                        \
         PY_CHECK_ARGC(2);                                                                          \
         PY_CHECK_ARG_TYPE(0, tp_int);                                                              \
         PY_CHECK_ARG_TYPE(1, tp_int);                                                              \
@@ -37,6 +49,7 @@
         return true;                                                                               \
     }                                                                                              \
     static bool stdc_##Char_##__write_STATIC(int argc, py_Ref argv) {                              \
+        if(!check_stdc_cap()) return false;                                                        \
         PY_CHECK_ARGC(3);                                                                          \
         PY_CHECK_ARG_TYPE(0, tp_int);                                                              \
         PY_CHECK_ARG_TYPE(1, tp_int);                                                              \
@@ -48,6 +61,7 @@
         return true;                                                                               \
     }                                                                                              \
     static bool stdc_##Char_##__array_STATIC(int argc, py_Ref argv) {                              \
+        if(!check_stdc_cap()) return false;                                                        \
         PY_CHECK_ARGC(1);                                                                          \
         PY_CHECK_ARG_TYPE(0, tp_int);                                                              \
         int length = py_toint(argv);                                                               \
@@ -56,6 +70,7 @@
         return true;                                                                               \
     }                                                                                              \
     static bool stdc_##Char_##__getitem__(int argc, py_Ref argv) {                                 \
+        if(!check_stdc_cap()) return false;                                                        \
         PY_CHECK_ARGC(2);                                                                          \
         char_* ud = py_touserdata(argv);                                                           \
         PY_CHECK_ARG_TYPE(1, tp_int);                                                              \
@@ -64,6 +79,7 @@
         return true;                                                                               \
     }                                                                                              \
     static bool stdc_##Char_##__setitem__(int argc, py_Ref argv) {                                 \
+        if(!check_stdc_cap()) return false;                                                        \
         PY_CHECK_ARGC(3);                                                                          \
         char_* ud = py_touserdata(argv);                                                           \
         PY_CHECK_ARG_TYPE(1, tp_int);                                                              \
@@ -105,6 +121,7 @@ DEF_BUILTIN_MEMORY_T(Bool, bool, tp_bool, py_newbool, py_tobool, bool)
 #undef DEF_BUILTIN_MEMORY_T
 
 static bool stdc_malloc(int argc, py_Ref argv) {
+    if(!check_stdc_cap()) return false;
     PY_CHECK_ARGC(1);
     PY_CHECK_ARG_TYPE(0, tp_int);
     py_i64 size = py_toint(&argv[0]);
@@ -114,6 +131,7 @@ static bool stdc_malloc(int argc, py_Ref argv) {
 }
 
 static bool stdc_free(int argc, py_Ref argv) {
+    if(!check_stdc_cap()) return false;
     PY_CHECK_ARGC(1);
     PY_CHECK_ARG_TYPE(0, tp_int);
     void* p = (void*)(intptr_t)py_toint(&argv[0]);
@@ -123,6 +141,7 @@ static bool stdc_free(int argc, py_Ref argv) {
 }
 
 static bool stdc_memcpy(int argc, py_Ref argv) {
+    if(!check_stdc_cap()) return false;
     PY_CHECK_ARGC(3);
     PY_CHECK_ARG_TYPE(0, tp_int);   // dst
     void* dst = (void*)(intptr_t)py_toint(&argv[0]);
@@ -143,6 +162,7 @@ static bool stdc_memcpy(int argc, py_Ref argv) {
 }
 
 static bool stdc_memset(int argc, py_Ref argv) {
+    if(!check_stdc_cap()) return false;
     PY_CHECK_ARGC(3);
     PY_CHECK_ARG_TYPE(0, tp_int);
     PY_CHECK_ARG_TYPE(1, tp_int);
@@ -156,6 +176,7 @@ static bool stdc_memset(int argc, py_Ref argv) {
 }
 
 static bool stdc_memcmp(int argc, py_Ref argv) {
+    if(!check_stdc_cap()) return false;
     PY_CHECK_ARGC(3);
     PY_CHECK_ARG_TYPE(0, tp_int);
     PY_CHECK_ARG_TYPE(1, tp_int);
@@ -169,6 +190,7 @@ static bool stdc_memcmp(int argc, py_Ref argv) {
 }
 
 static bool stdc_addressof(int argc, py_Ref argv) {
+    if(!check_stdc_cap()) return false;
     PY_CHECK_ARGC(1);
     if(!py_checkinstance(argv, tp_stdc_Memory)) return false;
     void* ud = py_touserdata(argv);
@@ -177,6 +199,7 @@ static bool stdc_addressof(int argc, py_Ref argv) {
 }
 
 static bool stdc_sizeof(int argc, py_Ref argv) {
+    if(!check_stdc_cap()) return false;
     PY_CHECK_ARGC(1);
     PY_CHECK_ARG_TYPE(0, tp_type);
     py_Type type = py_totype(&argv[0]);
@@ -188,6 +211,7 @@ static bool stdc_sizeof(int argc, py_Ref argv) {
 }
 
 static bool stdc_read_cstr(int argc, py_Ref argv) {
+    if(!check_stdc_cap()) return false;
     PY_CHECK_ARGC(1);
     PY_CHECK_ARG_TYPE(0, tp_int);
     char* p = (char*)(intptr_t)py_toint(&argv[0]);
@@ -196,6 +220,7 @@ static bool stdc_read_cstr(int argc, py_Ref argv) {
 }
 
 static bool stdc_write_cstr(int argc, py_Ref argv) {
+    if(!check_stdc_cap()) return false;
     PY_CHECK_ARGC(2);
     PY_CHECK_ARG_TYPE(0, tp_int);
     PY_CHECK_ARG_TYPE(1, tp_str);
@@ -208,6 +233,7 @@ static bool stdc_write_cstr(int argc, py_Ref argv) {
 }
 
 static bool stdc_read_bytes(int argc, py_Ref argv) {
+    if(!check_stdc_cap()) return false;
     PY_CHECK_ARGC(2);
     PY_CHECK_ARG_TYPE(0, tp_int);
     PY_CHECK_ARG_TYPE(1, tp_int);
@@ -219,6 +245,7 @@ static bool stdc_read_bytes(int argc, py_Ref argv) {
 }
 
 static bool stdc_write_bytes(int argc, py_Ref argv) {
+    if(!check_stdc_cap()) return false;
     PY_CHECK_ARGC(2);
     PY_CHECK_ARG_TYPE(0, tp_int);
     PY_CHECK_ARG_TYPE(1, tp_bytes);

+ 2 - 0
src/public/GlobalSetup.c

@@ -110,6 +110,8 @@ void py_setvmctx(void* ctx) { pk_current_vm->ctx = ctx; }
 
 py_Callbacks* py_callbacks() { return &pk_current_vm->callbacks; }
 
+py_Capabilities* py_capabilities() { return &pk_current_vm->capabilities; }
+
 py_AppCallbacks* py_appcallbacks() {
     static py_AppCallbacks _callbacks = {0};
     return &_callbacks;

+ 3 - 0
tests/300_import.py

@@ -1,3 +1,6 @@
+print('sandbox mode, module is disabled')
+exit()
+
 try:
     import os
 except ImportError:

+ 3 - 0
tests/301_import1.py

@@ -1,3 +1,6 @@
+print('sandbox mode, module is disabled')
+exit()
+
 try:
     import os
 except ImportError:

+ 3 - 0
tests/310_modulereload.py

@@ -1,3 +1,6 @@
+print('sandbox mode, module is disabled')
+exit()
+
 try:
     import os
 except ImportError:

+ 3 - 0
tests/792_file.py

@@ -1,3 +1,6 @@
+print('sandbox mode, module is disabled')
+exit()
+
 try:
     import os
     import io

+ 3 - 0
tests/793_stdc.py

@@ -1,3 +1,6 @@
+print('sandbox mode, module is disabled')
+exit()
+
 from stdc import *
 
 assert sizeof(Int8) == sizeof(UInt8) == 1

+ 3 - 0
tests/922_py_compile.py

@@ -1,3 +1,6 @@
+print('sandbox mode, module is disabled')
+exit()
+
 try:
     import os
 except ImportError:

+ 3 - 0
tests/931_math.py

@@ -1,3 +1,6 @@
+print('sandbox mode, module is disabled')
+exit()
+
 # https://github.com/python/cpython/blob/v3.4.10/Lib/test/test_math.py
 
 # Python test set -- math module