2222#include <pty.h>
2323#include <stdint.h>
2424#include <stdbool.h>
25+ #include <execinfo.h>
2526
2627#define CONFIG_FILE ".sandbox.conf"
2728#define KEY_BANNED_HOSTS "SANDBOX_PYTHON_BANNED_HOSTS"
2829#define KEY_ALLOW_DL_PATHS "SANDBOX_PYTHON_ALLOW_DL_PATHS"
30+ #define KEY_ALLOW_DL_OPEN "SANDBOX_PYTHON_ALLOW_DL_OPEN"
2931#define KEY_ALLOW_SUBPROCESS "SANDBOX_PYTHON_ALLOW_SUBPROCESS"
3032#define KEY_ALLOW_SYSCALL "SANDBOX_PYTHON_ALLOW_SYSCALL"
3133
3234static char * banned_hosts = NULL ;
3335static char * allow_dl_paths = NULL ;
36+ static int allow_dl_open = 0 ;
3437static int allow_subprocess = 0 ; // 默认禁止
3538static int allow_syscall = 0 ;
3639
@@ -39,6 +42,7 @@ static void load_sandbox_config() {
3942 if (dladdr ((void * )load_sandbox_config , & info ) == 0 || !info .dli_fname ) {
4043 banned_hosts = strdup ("" );
4144 allow_dl_paths = strdup ("" );
45+ allow_dl_open = 0 ;
4246 allow_subprocess = 0 ;
4347 allow_syscall = 0 ;
4448 return ;
@@ -53,6 +57,7 @@ static void load_sandbox_config() {
5357 if (!fp ) {
5458 banned_hosts = strdup ("" );
5559 allow_dl_paths = strdup ("" );
60+ allow_dl_open = 0 ;
5661 allow_subprocess = 0 ;
5762 allow_syscall = 0 ;
5863 return ;
@@ -62,6 +67,7 @@ static void load_sandbox_config() {
6267 if (allow_dl_paths ) { free (allow_dl_paths ); allow_dl_paths = NULL ; }
6368 banned_hosts = strdup ("" );
6469 allow_dl_paths = strdup ("" );
70+ allow_dl_open = 0 ;
6571 allow_subprocess = 0 ;
6672 allow_syscall = 0 ;
6773 while (fgets (line , sizeof (line ), fp )) {
@@ -80,6 +86,8 @@ static void load_sandbox_config() {
8086 } else if (strcmp (key , KEY_ALLOW_DL_PATHS ) == 0 ) {
8187 free (allow_dl_paths );
8288 allow_dl_paths = strdup (value ); // 逗号分隔字符串
89+ } else if (strcmp (key , KEY_ALLOW_DL_OPEN ) == 0 ) {
90+ allow_dl_open = atoi (value );
8391 } else if (strcmp (key , KEY_ALLOW_SUBPROCESS ) == 0 ) {
8492 allow_subprocess = atoi (value );
8593 } else if (strcmp (key , KEY_ALLOW_SYSCALL ) == 0 ) {
@@ -519,6 +527,7 @@ long syscall(long number, ...) {
519527#endif
520528 case SYS_fchmodat :
521529 case SYS_mprotect :
530+ case SYS_pkey_mprotect :
522531#ifdef SYS_open
523532 case SYS_open :
524533#endif
@@ -543,7 +552,24 @@ long syscall(long number, ...) {
543552/**
544553 * 限制加载动态链接库
545554 */
546- static int is_in_allow_dl_paths (const char * filename ) {
555+ static int called_from_python_import () {
556+ if (allow_dl_open ) return 1 ;
557+ void * buf [32 ];
558+ int n = backtrace (buf , 32 );
559+ for (int i = 0 ; i < n ; i ++ ) {
560+ Dl_info info ;
561+ if (dladdr (buf [i ], & info ) && info .dli_sname ) {
562+ if (strstr (info .dli_sname , "PyImport" ) ||
563+ strstr (info .dli_sname , "_PyImport" )) {
564+ return 1 ;
565+ }
566+ }
567+ }
568+ throw_permission_denied_err (true, "open dynamic link library" );
569+ return 0 ;
570+ }
571+ static int is_allow_dl (const char * filename ) {
572+ if (!called_from_python_import ()) return 0 ;
547573 if (!filename || !* filename ) return 1 ;
548574 ensure_config_loaded ();
549575 if (!allow_dl_paths || !* allow_dl_paths ) return 0 ;
@@ -570,7 +596,7 @@ static int is_in_allow_dl_paths(const char *filename) {
570596}
571597void * dlopen (const char * filename , int flag ) {
572598 RESOLVE_REAL (dlopen );
573- if (is_sandbox_user () && !is_in_allow_dl_paths (filename )) {
599+ if (is_sandbox_user () && !is_allow_dl (filename )) {
574600 throw_permission_denied_err (true, "access file %s" , filename );
575601 }
576602 return real_dlopen (filename , flag );
@@ -580,7 +606,7 @@ void *__dlopen(const char *filename, int flag) {
580606}
581607void * dlmopen (Lmid_t lmid , const char * filename , int flags ) {
582608 RESOLVE_REAL (dlmopen );
583- if (is_sandbox_user () && !is_in_allow_dl_paths (filename )) {
609+ if (is_sandbox_user () && !is_allow_dl (filename )) {
584610 throw_permission_denied_err (true, "access file %s" , filename );
585611 }
586612 return real_dlmopen (lmid , filename , flags );
@@ -602,7 +628,7 @@ void* mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off) {
602628 throw_permission_denied_err (true, "mmap(readlink failed)" );
603629 }
604630 real_path [n ] = '\0' ;
605- if (!is_in_allow_dl_paths (real_path )) {
631+ if (!is_allow_dl (real_path )) {
606632 throw_permission_denied_err (true, "mmap %s" , real_path );
607633 }
608634 }
0 commit comments