1 /**********************************************************************
2
3 safe.c -
4
5 $Author: ko1 $
6 created at: Tue Sep 23 09:44:32 JST 2008
7
8 Copyright (C) 2008 Yukihiro Matsumoto
9
10 **********************************************************************/
11
12 /* safe-level:
13 0 - strings from streams/environment/ARGV are tainted (default)
14 1 - no dangerous operation by tainted value
15 */
16
17 #define SAFE_LEVEL_MAX RUBY_SAFE_LEVEL_MAX
18
19 #include "ruby/ruby.h"
20 #include "vm_core.h"
21
22 /* $SAFE accessor */
23
24 #undef rb_secure
25 #undef rb_set_safe_level
26 #undef ruby_safe_level_2_warning
27
28 int
ruby_safe_level_2_warning(void)29 ruby_safe_level_2_warning(void)
30 {
31 return 2;
32 }
33
34 int
rb_safe_level(void)35 rb_safe_level(void)
36 {
37 return GET_VM()->safe_level_;
38 }
39
40 void
rb_set_safe_level_force(int safe)41 rb_set_safe_level_force(int safe)
42 {
43 GET_VM()->safe_level_ = safe;
44 }
45
46 void
rb_set_safe_level(int level)47 rb_set_safe_level(int level)
48 {
49 rb_vm_t *vm = GET_VM();
50
51 if (level > SAFE_LEVEL_MAX) {
52 rb_raise(rb_eArgError, "$SAFE=2 to 4 are obsolete");
53 }
54 else if (level < 0) {
55 rb_raise(rb_eArgError, "$SAFE should be >= 0");
56 }
57 else {
58 int line;
59 const char *path = rb_source_location_cstr(&line);
60
61 if (0) fprintf(stderr, "%s:%d $SAFE %d -> %d\n",
62 path ? path : "-", line, vm->safe_level_, level);
63
64 vm->safe_level_ = level;
65 }
66 }
67
68 static VALUE
safe_getter(void)69 safe_getter(void)
70 {
71 return INT2NUM(rb_safe_level());
72 }
73
74 static void
safe_setter(VALUE val)75 safe_setter(VALUE val)
76 {
77 int level = NUM2INT(val);
78 rb_set_safe_level(level);
79 }
80
81 void
rb_secure(int level)82 rb_secure(int level)
83 {
84 if (level <= rb_safe_level()) {
85 ID caller_name = rb_frame_callee();
86 if (caller_name) {
87 rb_raise(rb_eSecurityError, "Insecure operation `%"PRIsVALUE"' at level %d",
88 rb_id2str(caller_name), rb_safe_level());
89 }
90 else {
91 rb_raise(rb_eSecurityError, "Insecure operation at level %d",
92 rb_safe_level());
93 }
94 }
95 }
96
97 void
rb_secure_update(VALUE obj)98 rb_secure_update(VALUE obj)
99 {
100 }
101
102 void
rb_insecure_operation(void)103 rb_insecure_operation(void)
104 {
105 ID caller_name = rb_frame_callee();
106 if (caller_name) {
107 rb_raise(rb_eSecurityError, "Insecure operation - %"PRIsVALUE,
108 rb_id2str(caller_name));
109 }
110 else {
111 rb_raise(rb_eSecurityError, "Insecure operation: -r");
112 }
113 }
114
115 void
rb_check_safe_obj(VALUE x)116 rb_check_safe_obj(VALUE x)
117 {
118 if (rb_safe_level() > 0 && OBJ_TAINTED(x)) {
119 rb_insecure_operation();
120 }
121 }
122
123 void
Init_safe(void)124 Init_safe(void)
125 {
126 rb_define_virtual_variable("$SAFE", safe_getter, safe_setter);
127 }
128