ben@tanjero.com (author)
Tue Apr 07 22:06:27 -0700 2009
macruby / eval_safe.c
| ccf4d116 » | lsansonetti@apple.com | 2008-02-25 | 1 | /* -*-c-*- */ | |
| 2 | /* | ||||
| 3 | * This file is included by eval.c | ||||
| 4 | */ | ||||
| 5 | |||||
| 6 | /* safe-level: | ||||
| 7 | 0 - strings from streams/environment/ARGV are tainted (default) | ||||
| 8 | 1 - no dangerous operation by tainted value | ||||
| 9 | 2 - process/file operations prohibited | ||||
| 10 | 3 - all generated objects are tainted | ||||
| 11 | 4 - no global (non-tainted) variable modification/no direct output | ||||
| 12 | */ | ||||
| 13 | |||||
| 14 | #define SAFE_LEVEL_MAX 4 | ||||
| 15 | |||||
| 16 | /* $SAFE accessor */ | ||||
| 17 | |||||
| 18 | int | ||||
| 19 | rb_safe_level(void) | ||||
| 20 | { | ||||
| 21 | return GET_THREAD()->safe_level; | ||||
| 22 | } | ||||
| 23 | |||||
| 24 | void | ||||
| 25 | rb_set_safe_level_force(int safe) | ||||
| 26 | { | ||||
| 27 | GET_THREAD()->safe_level = safe; | ||||
| 28 | } | ||||
| 29 | |||||
| 30 | void | ||||
| 31 | rb_set_safe_level(int level) | ||||
| 32 | { | ||||
| 33 | rb_thread_t *th = GET_THREAD(); | ||||
| 34 | |||||
| 35 | if (level > th->safe_level) { | ||||
| 36 | if (level > SAFE_LEVEL_MAX) { | ||||
| 37 | level = SAFE_LEVEL_MAX; | ||||
| 38 | } | ||||
| 39 | th->safe_level = level; | ||||
| 40 | } | ||||
| 41 | } | ||||
| 42 | |||||
| 43 | static VALUE | ||||
| 44 | safe_getter(void) | ||||
| 45 | { | ||||
| 46 | return INT2NUM(rb_safe_level()); | ||||
| 47 | } | ||||
| 48 | |||||
| 49 | static void | ||||
| 50 | safe_setter(VALUE val) | ||||
| 51 | { | ||||
| 52 | int level = NUM2INT(val); | ||||
| 53 | rb_thread_t *th = GET_THREAD(); | ||||
| 54 | |||||
| 55 | if (level < th->safe_level) { | ||||
| 56 | rb_raise(rb_eSecurityError, | ||||
| 57 | "tried to downgrade safe level from %d to %d", | ||||
| 58 | th->safe_level, level); | ||||
| 59 | } | ||||
| 60 | if (level > SAFE_LEVEL_MAX) { | ||||
| 61 | level = SAFE_LEVEL_MAX; | ||||
| 62 | } | ||||
| 63 | th->safe_level = level; | ||||
| 64 | } | ||||
| 65 | |||||
| 66 | void | ||||
| 67 | rb_secure(int level) | ||||
| 68 | { | ||||
| 69 | if (level <= rb_safe_level()) { | ||||
| 70 | if (rb_frame_callee()) { | ||||
| 71 | rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d", | ||||
| 72 | rb_id2name(rb_frame_callee()), rb_safe_level()); | ||||
| 73 | } | ||||
| 74 | else { | ||||
| 75 | rb_raise(rb_eSecurityError, "Insecure operation at level %d", | ||||
| 76 | rb_safe_level()); | ||||
| 77 | } | ||||
| 78 | } | ||||
| 79 | } | ||||
| 80 | |||||
| 81 | void | ||||
| 82 | rb_secure_update(VALUE obj) | ||||
| 83 | { | ||||
| 84 | if (!OBJ_TAINTED(obj)) | ||||
| 85 | rb_secure(4); | ||||
| 86 | } | ||||
| 87 | |||||
| 88 | void | ||||
| 89 | rb_check_safe_obj(VALUE x) | ||||
| 90 | { | ||||
| 91 | if (rb_safe_level() > 0 && OBJ_TAINTED(x)) { | ||||
| 92 | if (rb_frame_callee()) { | ||||
| 93 | rb_raise(rb_eSecurityError, "Insecure operation - %s", | ||||
| 94 | rb_id2name(rb_frame_callee())); | ||||
| 95 | } | ||||
| 96 | else { | ||||
| 97 | rb_raise(rb_eSecurityError, "Insecure operation: -r"); | ||||
| 98 | } | ||||
| 99 | } | ||||
| 100 | rb_secure(4); | ||||
| 101 | } | ||||
| 102 | |||||
| 103 | void | ||||
| 104 | rb_check_safe_str(VALUE x) | ||||
| 105 | { | ||||
| 106 | rb_check_safe_obj(x); | ||||
| 107 | if (TYPE(x) != T_STRING) { | ||||
| 108 | rb_raise(rb_eTypeError, "wrong argument type %s (expected String)", | ||||
| 109 | rb_obj_classname(x)); | ||||
| 110 | } | ||||
| 111 | } | ||||
