InstallingTheSandbox: ruby-1.8.5-sandbox_needs.patch

File ruby-1.8.5-sandbox_needs.patch, 13.5 kB (added by why, 18 months ago)

Ruby 1.8.5 patch to add 'Thread#kill!' and some sandbox threading hooks.

  • ruby-1.8.

    diff -wur ruby-1.8.5/error.c ruby-1.8.5-sandbox/error.c
    old new  
    827827 *     Errno.constants   #=> E2BIG, EACCES, EADDRINUSE, EADDRNOTAVAIL, ... 
    828828 */ 
    829829 
    830 static st_table *syserr_tbl; 
     830st_table *rb_syserr_tbl; 
    831831 
    832832static VALUE 
    833833set_syserr(n, name) 
     
    836836{ 
    837837    VALUE error; 
    838838 
    839     if (!st_lookup(syserr_tbl, n, &error)) { 
     839    if (!st_lookup(rb_syserr_tbl, n, &error)) { 
    840840        error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError); 
    841841        rb_define_const(error, "Errno", INT2NUM(n)); 
    842         st_add_direct(syserr_tbl, n, error); 
     842        st_add_direct(rb_syserr_tbl, n, error); 
    843843    } 
    844844    else { 
    845845        rb_define_const(rb_mErrno, name, error); 
     
    853853{ 
    854854    VALUE error; 
    855855 
    856     if (!st_lookup(syserr_tbl, n, &error)) { 
     856    if (!st_lookup(rb_syserr_tbl, n, &error)) { 
    857857        char name[8];   /* some Windows' errno have 5 digits. */ 
    858858 
    859859        snprintf(name, sizeof(name), "E%03d", n); 
     
    891891        if (argc == 1 && FIXNUM_P(mesg)) { 
    892892            error = mesg; mesg = Qnil; 
    893893        } 
    894         if (!NIL_P(error) && st_lookup(syserr_tbl, NUM2LONG(error), &klass)) { 
     894        if (!NIL_P(error) && st_lookup(rb_syserr_tbl, NUM2LONG(error), &klass)) { 
    895895            /* change class */ 
    896896            if (TYPE(self) != T_OBJECT) { /* insurance to avoid type crash */ 
    897897                rb_raise(rb_eTypeError, "invalid instance type"); 
     
    10311031    rb_eSecurityError = rb_define_class("SecurityError", rb_eStandardError); 
    10321032    rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException); 
    10331033 
    1034     syserr_tbl = st_init_numtable(); 
     1034    rb_syserr_tbl = st_init_numtable(); 
    10351035    rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError); 
    10361036    rb_define_method(rb_eSystemCallError, "initialize", syserr_initialize, -1); 
    10371037    rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0); 
  • ruby-1.8.

    diff -wur ruby-1.8.5/eval.c ruby-1.8.5-sandbox/eval.c
    old new  
    2929#endif 
    3030 
    3131#include <stdio.h> 
    32 #if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT) 
    33 #include <ucontext.h> 
    34 #define USE_CONTEXT 
    35 #endif 
    36 #include <setjmp.h> 
    3732 
    3833#include "st.h" 
    3934#include "dln.h" 
     
    9085#endif 
    9186 
    9287#ifdef USE_CONTEXT 
    93 typedef struct { 
    94     ucontext_t context; 
    95     volatile int status; 
    96 } rb_jmpbuf_t[1]; 
    9788 
    9889NORETURN(static void rb_jump_context(rb_jmpbuf_t, int)); 
    9990static inline void 
     
    201192     POST_GETCONTEXT, \ 
    202193     (j)->status) 
    203194#else 
    204 typedef jmp_buf rb_jmpbuf_t; 
    205195#  if !defined(setjmp) && defined(HAVE__SETJMP) 
    206196#    define ruby_setjmp(env) _setjmp(env) 
    207197#    define ruby_longjmp(env,val) _longjmp(env,val) 
     
    250240#define SCOPE_SET(f)  (scope_vmode=(f)) 
    251241#define SCOPE_TEST(f) (scope_vmode&(f)) 
    252242 
     243VALUE (*ruby_sandbox_save)(struct thread *) = NULL;  
     244VALUE (*ruby_sandbox_restore)(struct thread *) = NULL;  
    253245NODE* ruby_current_node; 
    254246int ruby_safe_level = 0; 
    255247/* safe-level: 
     
    10611053#define POP_CLASS() ruby_class = _class; \ 
    10621054} while (0) 
    10631055 
    1064 static NODE *ruby_cref = 0; 
    1065 static NODE *top_cref; 
     1056NODE *ruby_cref = 0; 
     1057NODE *ruby_top_cref; 
    10661058#define PUSH_CREF(c) ruby_cref = NEW_NODE(NODE_CREF,(c),0,ruby_cref) 
    10671059#define POP_CREF() ruby_cref = ruby_cref->nd_next 
    10681060 
     
    10781070    ruby_scope = _scope;                \ 
    10791071    scope_vmode = SCOPE_PUBLIC 
    10801072 
    1081 typedef struct thread * rb_thread_t; 
    1082 static rb_thread_t curr_thread = 0; 
    1083 static rb_thread_t main_thread; 
     1073rb_thread_t curr_thread = 0; 
     1074rb_thread_t main_thread; 
    10841075static void scope_dup _((struct SCOPE *)); 
    10851076 
    10861077#define POP_SCOPE()                     \ 
     
    13911382        rb_call_inits(); 
    13921383        ruby_class = rb_cObject; 
    13931384        ruby_frame->self = ruby_top_self; 
    1394         top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0); 
    1395         ruby_cref = top_cref; 
     1385        ruby_top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0); 
     1386        ruby_cref = ruby_top_cref; 
    13961387        rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(ruby_top_self)); 
    13971388#ifdef __MACOS__ 
    13981389        _macruby_init(); 
     
    14371428static int thread_set_raised(); 
    14381429static int thread_reset_raised(); 
    14391430 
     1431static int thread_no_ensure _((void)); 
     1432 
    14401433static VALUE exception_error; 
    14411434static VALUE sysstack_error; 
    14421435 
     
    33073300            result = rb_eval(self, node->nd_head); 
    33083301        } 
    33093302        POP_TAG(); 
    3310         if (node->nd_ensr) { 
     3303        if (node->nd_ensr && !thread_no_ensure()) { 
    33113304            VALUE retval = prot_tag->retval; /* save retval */ 
    33123305            VALUE errinfo = ruby_errinfo; 
    33133306 
     
    47404733    return Qfalse; 
    47414734} 
    47424735 
    4743 static VALUE rb_eThreadError; 
     4736VALUE rb_eThreadError; 
    47444737 
    47454738NORETURN(static void proc_jump_error(int, VALUE)); 
    47464739static void 
     
    54535446    } 
    54545447    POP_TAG(); 
    54555448    retval = prot_tag ? prot_tag->retval : Qnil;        /* save retval */ 
     5449    if (!thread_no_ensure()) { 
    54565450    (*e_proc)(data2); 
     5451    } 
    54575452    if (prot_tag) return_value(retval); 
    54585453    if (state) JUMP_TAG(state); 
    54595454    return result; 
     
    67976792    ruby_errinfo = Qnil;        /* ensure */ 
    67986793    PUSH_VARS(); 
    67996794    PUSH_CLASS(ruby_wrapper); 
    6800     ruby_cref = top_cref; 
     6795    ruby_cref = ruby_top_cref; 
    68016796    if (!wrap) { 
    68026797        rb_secure(4);           /* should alter global state */ 
    68036798        ruby_class = rb_cObject; 
     
    97579752 
    97589753extern VALUE rb_last_status; 
    97599754 
    9760 enum thread_status { 
    9761     THREAD_TO_KILL, 
    9762     THREAD_RUNNABLE, 
    9763     THREAD_STOPPED, 
    9764     THREAD_KILLED, 
    9765 }; 
    9766  
    97679755#define WAIT_FD         (1<<0) 
    97689756#define WAIT_SELECT     (1<<1) 
    97699757#define WAIT_TIME       (1<<2) 
     
    97819769# endif 
    97829770#endif 
    97839771 
    9784 /* typedef struct thread * rb_thread_t; */ 
    9785  
    9786 struct thread { 
    9787     struct thread *next, *prev; 
    9788     rb_jmpbuf_t context; 
    9789 #ifdef SAVE_WIN32_EXCEPTION_LIST 
    9790     DWORD win32_exception_list; 
    9791 #endif 
    9792  
    9793     VALUE result; 
    9794  
    9795     long   stk_len; 
    9796     long   stk_max; 
    9797     VALUE *stk_ptr; 
    9798     VALUE *stk_pos; 
    9799 #ifdef __ia64__ 
    9800     VALUE *bstr_ptr; 
    9801     long   bstr_len; 
    9802 #endif 
    9803  
    9804     struct FRAME *frame; 
    9805     struct SCOPE *scope; 
    9806     struct RVarmap *dyna_vars; 
    9807     struct BLOCK *block; 
    9808     struct iter *iter; 
    9809     struct tag *tag; 
    9810     VALUE klass; 
    9811     VALUE wrapper; 
    9812     NODE *cref; 
    9813  
    9814     int flags;          /* misc. states (vmode/rb_trap_immediate/raised) */ 
    9815  
    9816     NODE *node; 
    9817  
    9818     int tracing; 
    9819     VALUE errinfo; 
    9820     VALUE last_status; 
    9821     VALUE last_line; 
    9822     VALUE last_match; 
    9823  
    9824     int safe; 
    9825  
    9826     enum thread_status status; 
    9827     int wait_for; 
    9828     int fd; 
    9829     fd_set readfds; 
    9830     fd_set writefds; 
    9831     fd_set exceptfds; 
    9832     int select_value; 
    9833     double delay; 
    9834     rb_thread_t join; 
    9835  
    9836     int abort; 
    9837     int priority; 
    9838     VALUE thgroup; 
    9839  
    9840     st_table *locals; 
    9841  
    9842     VALUE thread; 
    9843 }; 
    9844  
    98459772#define THREAD_RAISED 0x200      /* temporary flag */ 
    98469773#define THREAD_TERMINATING 0x400 /* persistent flag */ 
    9847 #define THREAD_FLAGS_MASK  0x400 /* mask for persistent flags */ 
     9774#define THREAD_NO_ENSURE 0x800   /* persistent flag */ 
     9775#define THREAD_FLAGS_MASK  0xc00 /* mask for persistent flags */ 
    98489776 
    98499777#define FOREACH_THREAD_FROM(f,x) x = f; do { x = x->next; 
    98509778#define END_FOREACH_FROM(f,x) } while (x != f) 
     
    99129840    return 1; 
    99139841} 
    99149842 
     9843static int 
     9844thread_no_ensure() 
     9845{ 
     9846    return ((curr_thread->flags & THREAD_NO_ENSURE) == THREAD_NO_ENSURE); 
     9847} 
     9848 
    99159849static void rb_thread_ready _((rb_thread_t)); 
    99169850 
    99179851static VALUE run_trap_eval _((VALUE)); 
     
    100429976    rb_gc_mark(th->last_match); 
    100439977    rb_mark_tbl(th->locals); 
    100449978    rb_gc_mark(th->thgroup); 
     9979    rb_gc_mark_maybe(th->sandbox); 
    100459980 
    100469981    /* mark data in copied stack */ 
    100479982    if (th == curr_thread) return; 
     
    1024610181    th->safe = ruby_safe_level; 
    1024710182 
    1024810183    th->node = ruby_current_node; 
     10184    if (ruby_sandbox_save != NULL) 
     10185    { 
     10186      ruby_sandbox_save(th); 
     10187    } 
    1024910188} 
    1025010189 
    1025110190static int 
     
    1033610275#endif 
    1033710276 
    1033810277    rb_trap_immediate = 0;      /* inhibit interrupts from here */ 
     10278    if (ruby_sandbox_restore != NULL) 
     10279    { 
     10280      ruby_sandbox_restore(th); 
     10281    } 
    1033910282    ruby_frame = th->frame; 
    1034010283    ruby_scope = th->scope; 
    1034110284    ruby_class = th->klass; 
     
    1120111144} 
    1120211145 
    1120311146 
     11147static void 
     11148kill_thread(th, flags) 
     11149    rb_thread_t th; 
     11150    int flags; 
     11151{ 
     11152    if (th != curr_thread && th->safe < 4) { 
     11153        rb_secure(4); 
     11154    } 
     11155    if (th->status == THREAD_TO_KILL || th->status == THREAD_KILLED) 
     11156        return; 
     11157    if (th == th->next || th == main_thread) rb_exit(EXIT_SUCCESS); 
     11158 
     11159    rb_thread_ready(th); 
     11160    th->flags |= flags; 
     11161    th->status = THREAD_TO_KILL; 
     11162    if (!rb_thread_critical) rb_thread_schedule(); 
     11163} 
     11164 
     11165 
    1120411166/* 
    1120511167 *  call-seq: 
    11206  *     thr.exit        => thr or nil 
    11207  *     thr.kill        => thr or nil 
    11208  *     thr.terminate   => thr or nil 
    11209  *   
    11210  *  Terminates <i>thr</i> and schedules another thread to be run. If this thread 
    11211  *  is already marked to be killed, <code>exit</code> returns the 
    11212  *  <code>Thread</code>. If this is the main thread, or the last thread, exits 
    11213  *  the process. 
     11168 *     thr.exit        => thr 
     11169 *     thr.kill        => thr 
     11170 *     thr.terminate   => thr 
     11171 *   
     11172 *  Terminates <i>thr</i> and schedules another thread to be run, returning 
     11173 *  the terminated <code>Thread</code>.  If this is the main thread, or the 
     11174 *  last thread, exits the process. 
    1121411175 */ 
    1121511176 
    1121611177VALUE 
     
    1121911180{ 
    1122011181    rb_thread_t th = rb_thread_check(thread); 
    1122111182 
    11222     if (th != curr_thread && th->safe < 4) { 
    11223         rb_secure(4); 
    11224     } 
    11225     if (th->status == THREAD_TO_KILL || th->status == THREAD_KILLED) 
     11183    kill_thread(th, 0); 
    1122611184        return thread; 
    11227     if (th == th->next || th == main_thread) rb_exit(EXIT_SUCCESS); 
     11185} 
    1122811186 
    11229     rb_thread_ready(th); 
    11230     th->status = THREAD_TO_KILL; 
    11231     if (!rb_thread_critical) rb_thread_schedule(); 
     11187 
     11188/* 
     11189 *  call-seq: 
     11190 *     thr.exit!        => thr 
     11191 *     thr.kill!        => thr 
     11192 *     thr.terminate!   => thr 
     11193 *   
     11194 *  Terminates <i>thr</i> without calling ensure clauses and schedules 
     11195 *  another thread to be run, returning the terminated <code>Thread</code>. 
     11196 *  If this is the main thread, or the last thread, exits the process. 
     11197 * 
     11198 *  See <code>Thread#exit</code> for the safer version. 
     11199 */ 
     11200 
     11201static VALUE 
     11202rb_thread_kill_bang(thread) 
     11203    VALUE thread; 
     11204{ 
     11205    rb_thread_t th = rb_thread_check(thread); 
     11206    kill_thread(th, THREAD_NO_ENSURE); 
    1123211207    return thread; 
    1123311208} 
    1123411209 
    11235  
    1123611210/* 
    1123711211 *  call-seq: 
    1123811212 *     Thread.kill(thread)   => thread 
     
    1162611600    th->thgroup = thgroup_default;\ 
    1162711601    th->locals = 0;\ 
    1162811602    th->thread = 0;\ 
     11603    if (curr_thread == 0) {\ 
     11604      th->sandbox = Qnil;\ 
     11605    } else {\ 
     11606      th->sandbox = curr_thread->sandbox;\ 
     11607    }\ 
    1162911608} while (0) 
    1163011609 
    1163111610static rb_thread_t 
     
    1288312862    rb_define_method(rb_cThread, "kill", rb_thread_kill, 0); 
    1288412863    rb_define_method(rb_cThread, "terminate", rb_thread_kill, 0); 
    1288512864    rb_define_method(rb_cThread, "exit", rb_thread_kill, 0); 
     12865    rb_define_method(rb_cThread, "kill!", rb_thread_kill_bang, 0); 
     12866    rb_define_method(rb_cThread, "terminate!", rb_thread_kill_bang, 0); 
     12867    rb_define_method(rb_cThread, "exit!", rb_thread_kill_bang, 0); 
    1288612868    rb_define_method(rb_cThread, "value", rb_thread_value, 0); 
    1288712869    rb_define_method(rb_cThread, "status", rb_thread_status, 0); 
    1288812870    rb_define_method(rb_cThread, "join", rb_thread_join_m, -1); 
  • ruby-1.8.

    diff -wur ruby-1.8.5/node.h ruby-1.8.5-sandbox/node.h
    old new  
    151151    } u3; 
    152152} NODE; 
    153153 
     154extern NODE *ruby_cref; 
     155extern NODE *ruby_top_cref; 
     156 
    154157#define RNODE(obj)  (R_CAST(RNode)(obj)) 
    155158 
    156159#define nd_type(n) ((int)(((RNODE(n))->flags>>FL_USHIFT)&0xff)) 
     
    371374void rb_add_event_hook _((rb_event_hook_func_t,rb_event_t)); 
    372375int rb_remove_event_hook _((rb_event_hook_func_t)); 
    373376 
     377#if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT) 
     378#include <ucontext.h> 
     379#define USE_CONTEXT 
     380#endif 
     381#include <setjmp.h> 
     382#include "st.h" 
     383 
     384#ifdef USE_CONTEXT 
     385typedef struct { 
     386    ucontext_t context; 
     387    volatile int status; 
     388} rb_jmpbuf_t[1]; 
     389#else 
     390typedef jmp_buf rb_jmpbuf_t; 
     391#endif 
     392 
     393enum thread_status { 
     394    THREAD_TO_KILL, 
     395    THREAD_RUNNABLE, 
     396    THREAD_STOPPED, 
     397    THREAD_KILLED, 
     398}; 
     399 
     400typedef struct thread * rb_thread_t; 
     401 
     402struct thread { 
     403    struct thread *next, *prev; 
     404    rb_jmpbuf_t context; 
     405#ifdef SAVE_WIN32_EXCEPTION_LIST 
     406    DWORD win32_exception_list; 
     407#endif 
     408 
     409    VALUE result; 
     410 
     411    long   stk_len; 
     412    long   stk_max; 
     413    VALUE *stk_ptr; 
     414    VALUE *stk_pos; 
     415#ifdef __ia64__ 
     416    VALUE *bstr_ptr; 
     417    long   bstr_len; 
     418#endif 
     419 
     420    struct FRAME *frame; 
     421    struct SCOPE *scope; 
     422    struct RVarmap *dyna_vars; 
     423    struct BLOCK *block; 
     424    struct iter *iter; 
     425    struct tag *tag; 
     426    VALUE klass; 
     427    VALUE wrapper; 
     428    NODE *cref; 
     429 
     430    int flags;          /* misc. states (vmode/rb_trap_immediate/raised) */ 
     431 
     432    NODE *node; 
     433 
     434    int tracing; 
     435    VALUE errinfo; 
     436    VALUE last_status; 
     437    VALUE last_line; 
     438    VALUE last_match; 
     439 
     440    int safe; 
     441 
     442    enum thread_status status; 
     443    int wait_for; 
     444    int fd; 
     445    fd_set readfds; 
     446    fd_set writefds; 
     447    fd_set exceptfds; 
     448    int select_value; 
     449    double delay; 
     450    rb_thread_t join; 
     451 
     452    int abort; 
     453    int priority; 
     454    VALUE thgroup; 
     455 
     456    st_table *locals; 
     457 
     458    VALUE thread; 
     459 
     460    VALUE sandbox; 
     461}; 
     462 
     463extern VALUE (*ruby_sandbox_save)(struct thread *);  
     464extern VALUE (*ruby_sandbox_restore)(struct thread *);  
     465extern rb_thread_t curr_thread; 
     466extern rb_thread_t main_thread; 
     467 
    374468#if defined(__cplusplus) 
    375469}  /* extern "C" { */ 
    376470#endif 
  • ruby-1.8.

    diff -wur ruby-1.8.5/ruby.h ruby-1.8.5-sandbox/ruby.h
    old new  
    626626RUBY_EXTERN VALUE rb_eRuntimeError; 
    627627RUBY_EXTERN VALUE rb_eSecurityError; 
    628628RUBY_EXTERN VALUE rb_eSystemCallError; 
     629RUBY_EXTERN VALUE rb_eThreadError; 
    629630RUBY_EXTERN VALUE rb_eTypeError; 
    630631RUBY_EXTERN VALUE rb_eZeroDivError; 
    631632RUBY_EXTERN VALUE rb_eNotImpError;