|
|
@@ -22,3 +22,96 @@ Index: ext/dbm/extconf.rb
|
|
|
db_check(dblib) and break
|
|
|
end
|
|
|
end
|
|
|
+
|
|
|
+-----------------------------------------------------------------------------
|
|
|
+
|
|
|
+Security Fixes (CVE-2006-3694)
|
|
|
+
|
|
|
+- eval.c, alias(): preserve current safe level
|
|
|
+ http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/ruby/eval.c?cvsroot=src&r1=1.616.2.166&r2=1.616.2.167
|
|
|
+ (only relevant part)
|
|
|
+- re.c: do not modify untainted levels in safe levels > 3
|
|
|
+ http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/ruby/re.c?cvsroot=src&r1=1.114.2.17&r2=1.114.2.18
|
|
|
+ (only last hunk is relevant)
|
|
|
+- dir.c: should not close untainted dir stream
|
|
|
+ http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/ruby/dir.c?cvsroot=src&r1=1.92.2.32&r2=1.92.2.33
|
|
|
+
|
|
|
+Index: dir.c
|
|
|
+--- dir.c.orig 2005-09-14 15:40:58 +0200
|
|
|
++++ dir.c 2006-07-28 10:47:57 +0200
|
|
|
+@@ -325,7 +325,17 @@
|
|
|
+ rb_raise(rb_eIOError, "closed directory");
|
|
|
+ }
|
|
|
+
|
|
|
++static void
|
|
|
++dir_check(dir)
|
|
|
++ VALUE dir;
|
|
|
++{
|
|
|
++ if (!OBJ_TAINTED(dir) && rb_safe_level() >= 4)
|
|
|
++ rb_raise(rb_eSecurityError, "Insecure: operation on untainted Dir");
|
|
|
++ rb_check_frozen(dir);
|
|
|
++}
|
|
|
++
|
|
|
+ #define GetDIR(obj, dirp) do {\
|
|
|
++ dir_check(dir);\
|
|
|
+ Data_Get_Struct(obj, struct dir_data, dirp);\
|
|
|
+ if (dirp->dir == NULL) dir_closed();\
|
|
|
+ } while (0)
|
|
|
+@@ -536,6 +546,9 @@
|
|
|
+ {
|
|
|
+ struct dir_data *dirp;
|
|
|
+
|
|
|
++ if (rb_safe_level() >= 4 && !OBJ_TAINTED(dir)) {
|
|
|
++ rb_raise(rb_eSecurityError, "Insecure: can't close");
|
|
|
++ }
|
|
|
+ GetDIR(dir, dirp);
|
|
|
+ closedir(dirp->dir);
|
|
|
+ dirp->dir = NULL;
|
|
|
+Index: eval.c
|
|
|
+--- eval.c.orig 2005-12-20 14:41:47 +0100
|
|
|
++++ eval.c 2006-07-28 10:47:57 +0200
|
|
|
+@@ -2097,7 +2097,8 @@
|
|
|
+ }
|
|
|
+ }
|
|
|
+ st_insert(RCLASS(klass)->m_tbl, name,
|
|
|
+- (st_data_t)NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex));
|
|
|
++ (st_data_t)NEW_METHOD(NEW_FBODY(body, def, origin),
|
|
|
++ NOEX_WITH_SAFE(orig->nd_noex)));
|
|
|
+ if (singleton) {
|
|
|
+ rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
|
|
|
+ }
|
|
|
+@@ -5638,6 +5639,11 @@
|
|
|
+ TMP_PROTECT;
|
|
|
+ volatile int safe = -1;
|
|
|
+
|
|
|
++ if (NOEX_SAFE(flags) > ruby_safe_level &&
|
|
|
++ !(flags&NOEX_TAINTED) && ruby_safe_level == 0 && NOEX_SAFE(flags) > 2) {
|
|
|
++ rb_raise(rb_eSecurityError, "calling insecure method: %s",
|
|
|
++ rb_id2name(id));
|
|
|
++ }
|
|
|
+ switch (ruby_iter->iter) {
|
|
|
+ case ITER_PRE:
|
|
|
+ case ITER_PAS:
|
|
|
+@@ -5742,10 +5748,6 @@
|
|
|
+ b2 = body = body->nd_next;
|
|
|
+
|
|
|
+ if (NOEX_SAFE(flags) > ruby_safe_level) {
|
|
|
+- if (!(flags&NOEX_TAINTED) && ruby_safe_level == 0 && NOEX_SAFE(flags) > 2) {
|
|
|
+- rb_raise(rb_eSecurityError, "calling insecure method: %s",
|
|
|
+- rb_id2name(id));
|
|
|
+- }
|
|
|
+ safe = ruby_safe_level;
|
|
|
+ ruby_safe_level = NOEX_SAFE(flags);
|
|
|
+ }
|
|
|
+Index: re.c
|
|
|
+--- re.c.orig 2005-12-13 04:27:51 +0100
|
|
|
++++ re.c 2006-07-28 10:47:57 +0200
|
|
|
+@@ -1332,6 +1332,8 @@
|
|
|
+ {
|
|
|
+ struct RRegexp *re = RREGEXP(obj);
|
|
|
+
|
|
|
++ if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
|
|
|
++ rb_raise(rb_eSecurityError, "Insecure: can't modify regexp");
|
|
|
+ if (re->ptr) re_free_pattern(re->ptr);
|
|
|
+ if (re->str) free(re->str);
|
|
|
+ re->ptr = 0;
|