Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /********************************************************************** 00002 00003 safe.c - 00004 00005 $Author: nobu $ 00006 created at: Tue Sep 23 09:44:32 JST 2008 00007 00008 Copyright (C) 2008 Yukihiro Matsumoto 00009 00010 **********************************************************************/ 00011 00012 /* safe-level: 00013 0 - strings from streams/environment/ARGV are tainted (default) 00014 1 - no dangerous operation by tainted value 00015 2 - process/file operations prohibited 00016 3 - all generated objects are tainted 00017 4 - no global (non-tainted) variable modification/no direct output 00018 */ 00019 00020 #define SAFE_LEVEL_MAX 4 00021 00022 #include "ruby/ruby.h" 00023 #include "vm_core.h" 00024 00025 /* $SAFE accessor */ 00026 00027 int 00028 rb_safe_level(void) 00029 { 00030 return GET_THREAD()->safe_level; 00031 } 00032 00033 void 00034 rb_set_safe_level_force(int safe) 00035 { 00036 GET_THREAD()->safe_level = safe; 00037 } 00038 00039 void 00040 rb_set_safe_level(int level) 00041 { 00042 rb_thread_t *th = GET_THREAD(); 00043 00044 if (level > th->safe_level) { 00045 if (level > SAFE_LEVEL_MAX) { 00046 level = SAFE_LEVEL_MAX; 00047 } 00048 th->safe_level = level; 00049 } 00050 } 00051 00052 static VALUE 00053 safe_getter(void) 00054 { 00055 return INT2NUM(rb_safe_level()); 00056 } 00057 00058 static void 00059 safe_setter(VALUE val) 00060 { 00061 int level = NUM2INT(val); 00062 rb_thread_t *th = GET_THREAD(); 00063 00064 if (level < th->safe_level) { 00065 rb_raise(rb_eSecurityError, 00066 "tried to downgrade safe level from %d to %d", 00067 th->safe_level, level); 00068 } 00069 if (level == 3) { 00070 rb_warning("$SAFE=3 does no sandboxing; you might want to use $SAFE=4"); 00071 } 00072 if (level > SAFE_LEVEL_MAX) { 00073 level = SAFE_LEVEL_MAX; 00074 } 00075 th->safe_level = level; 00076 } 00077 00078 void 00079 rb_secure(int level) 00080 { 00081 if (level <= rb_safe_level()) { 00082 if (rb_frame_callee()) { 00083 rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d", 00084 rb_id2name(rb_frame_callee()), rb_safe_level()); 00085 } 00086 else { 00087 rb_raise(rb_eSecurityError, "Insecure operation at level %d", 00088 rb_safe_level()); 00089 } 00090 } 00091 } 00092 00093 void 00094 rb_secure_update(VALUE obj) 00095 { 00096 if (!OBJ_TAINTED(obj)) 00097 rb_secure(4); 00098 } 00099 00100 void 00101 rb_insecure_operation(void) 00102 { 00103 if (rb_frame_callee()) { 00104 rb_raise(rb_eSecurityError, "Insecure operation - %s", 00105 rb_id2name(rb_frame_callee())); 00106 } 00107 else { 00108 rb_raise(rb_eSecurityError, "Insecure operation: -r"); 00109 } 00110 } 00111 00112 void 00113 rb_check_safe_obj(VALUE x) 00114 { 00115 if (rb_safe_level() > 0 && OBJ_TAINTED(x)) { 00116 rb_insecure_operation(); 00117 } 00118 rb_secure(4); 00119 } 00120 00121 void 00122 rb_check_safe_str(VALUE x) 00123 { 00124 rb_check_safe_obj(x); 00125 if (!RB_TYPE_P(x, T_STRING)) { 00126 rb_raise(rb_eTypeError, "wrong argument type %s (expected String)", 00127 rb_obj_classname(x)); 00128 } 00129 } 00130 00131 void 00132 Init_safe(void) 00133 { 00134 rb_define_virtual_variable("$SAFE", safe_getter, safe_setter); 00135 } 00136