Date: Fri, 21 Oct 2005 15:39:43 -0600 (MDT) From: Phil Oleson <oz@nixil.net> To: FreeBSD-gnats-submit@FreeBSD.org Subject: ports/87816: [PATCH] ruby18 & ruby16 - Security Vulnerability Message-ID: <200510212139.j9LLdhS6068291@nixil.net> Resent-Message-ID: <200510212140.j9LLeHV1099426@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 87816 >Category: ports >Synopsis: [PATCH] ruby18 & ruby16 - Security Vulnerability >Confidential: no >Severity: critical >Priority: high >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: update >Submitter-Id: current-users >Arrival-Date: Fri Oct 21 21:40:16 GMT 2005 >Closed-Date: >Last-Modified: >Originator: Phil Oleson >Release: FreeBSD 4.7-RELEASE-p28 i386 >Organization: N/A >Environment: System: FreeBSD nixil.net 4.7-RELEASE-p28 FreeBSD 4.7-RELEASE-p28 #42: Tue Jun 21 10:33:20 MDT 2005 root@fc2:/usr/src/sys/compile/nixil i386 >Description: Patches to fix CAN-2005-2337 for ruby18 & ruby16 ref: http://www.ruby-lang.org/en/20051003.html >How-To-Repeat: N/A >Fix: --- patch-ruby18 begins here --- diff -ruN ruby18.orig/Makefile ruby18/Makefile --- ruby18.orig/Makefile Sun Jul 3 04:26:31 2005 +++ ruby18/Makefile Fri Oct 21 15:24:51 2005 @@ -7,7 +7,7 @@ PORTNAME= ruby PORTVERSION= ${RUBY_PORTVERSION} -PORTREVISION= 4 +PORTREVISION= 5 CATEGORIES= lang ruby ipv6 MASTER_SITES= ${MASTER_SITE_RUBY} MASTER_SITE_SUBDIR= ${MASTER_SITE_SUBDIR_RUBY} diff -ruN ruby18.orig/files/patch-eval.c ruby18/files/patch-eval.c --- ruby18.orig/files/patch-eval.c Wed Dec 31 17:00:00 1969 +++ ruby18/files/patch-eval.c Fri Oct 21 15:24:20 2005 @@ -0,0 +1,100 @@ +--- eval.c.orig 2004-12-18 11:07:29.000000000 +0900 ++++ eval.c 2005-09-21 16:53:31.127896405 +0900 +@@ -254,2 +254,7 @@ + ++#define NOEX_TAINTED 8 ++#define NOEX_SAFE(n) ((n) >> 4) ++#define NOEX_WITH(n, v) ((n) | (v) << 4) ++#define NOEX_WITH_SAFE(n) NOEX_WITH(n, ruby_safe_level) ++ + void +@@ -346,3 +351,3 @@ + rb_clear_cache_by_id(mid); +- body = NEW_METHOD(node, noex); ++ body = NEW_METHOD(node, NOEX_WITH_SAFE(noex)); + st_insert(RCLASS(klass)->m_tbl, mid, (st_data_t)body); +@@ -5458,3 +5463,3 @@ + static VALUE +-rb_call0(klass, recv, id, oid, argc, argv, body, nosuper) ++rb_call0(klass, recv, id, oid, argc, argv, body, flags) + VALUE klass, recv; +@@ -5465,3 +5470,3 @@ + NODE *body; /* OK */ +- int nosuper; ++ int flags; + { +@@ -5472,2 +5477,3 @@ + TMP_PROTECT; ++ volatile int safe = -1; + +@@ -5493,3 +5499,3 @@ + ruby_frame->orig_func = oid; +- ruby_frame->last_class = nosuper?0:klass; ++ ruby_frame->last_class = (flags & NOEX_UNDEF)?0:klass; + ruby_frame->self = recv; +@@ -5555,3 +5561,2 @@ + PUSH_SCOPE(); +- + if (body->nd_rval) { +@@ -5574,5 +5579,12 @@ + ++ 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); ++ } + PUSH_VARS(); + PUSH_TAG(PROT_FUNC); +- + if ((state = EXEC_TAG()) == 0) { +@@ -5655,2 +5667,3 @@ + } ++ if (safe >= 0) ruby_safe_level = safe; + POP_TAG(); +@@ -5742,3 +5755,3 @@ + +- return rb_call0(klass, recv, mid, id, argc, argv, body, noex & NOEX_NOSUPER); ++ return rb_call0(klass, recv, mid, id, argc, argv, body, noex); + } +@@ -8532,2 +8545,3 @@ + ID id, oid; ++ int safe_level; + NODE *body; +@@ -8579,2 +8593,3 @@ + data->oid = oid; ++ data->safe_level = NOEX_WITH_SAFE(0); + OBJ_INFECT(method, klass); +@@ -8663,2 +8678,3 @@ + data->oid = orig->oid; ++ data->safe_level = NOEX_WITH_SAFE(0); + OBJ_INFECT(method, obj); +@@ -8784,4 +8800,3 @@ + struct METHOD *data; +- int state; +- volatile int safe = -1; ++ int safe; + +@@ -8791,15 +8806,11 @@ + } +- PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT); +- PUSH_TAG(PROT_NONE); + if (OBJ_TAINTED(method)) { +- safe = ruby_safe_level; +- if (ruby_safe_level < 4) ruby_safe_level = 4; ++ safe = NOEX_WITH(data->safe_level, 4)|NOEX_TAINTED; + } +- if ((state = EXEC_TAG()) == 0) { +- result = rb_call0(data->klass,data->recv,data->id,data->oid,argc,argv,data->body,0); ++ else { ++ safe = data->safe_level; + } +- POP_TAG(); ++ PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT); ++ result = rb_call0(data->klass,data->recv,data->id,data->oid,argc,argv,data->body,safe); + POP_ITER(); +- if (safe >= 0) ruby_safe_level = safe; +- if (state) JUMP_TAG(state); + return result; --- patch-ruby18 ends here --- --- patch-ruby16 begins here --- diff -ruN ruby16.orig/Makefile ruby16/Makefile --- ruby16.orig/Makefile Fri Oct 21 15:28:45 2005 +++ ruby16/Makefile Fri Oct 21 15:31:11 2005 @@ -7,7 +7,7 @@ PORTNAME= ruby PORTVERSION= ${RUBY_PORTVERSION} -PORTREVISION= 1 +PORTREVISION= 2 CATEGORIES= lang ruby ipv6 MASTER_SITES= ${MASTER_SITE_RUBY} MASTER_SITE_SUBDIR= ${MASTER_SITE_SUBDIR_RUBY} diff -ruN ruby16.orig/files/patch-eval.c ruby16/files/patch-eval.c --- ruby16.orig/files/patch-eval.c Wed Dec 31 17:00:00 1969 +++ ruby16/files/patch-eval.c Fri Oct 21 15:29:15 2005 @@ -0,0 +1,105 @@ +--- /tmp/eval.c 2005-09-21 01:37:35.144705141 +0900 ++++ eval.c 2005-09-21 01:32:05.458758905 +0900 +@@ -244,2 +244,7 @@ + ++#define NOEX_TAINTED 8 ++#define NOEX_SAFE(n) ((n) >> 4) ++#define NOEX_WITH(n, v) ((n) | (v) << 4) ++#define NOEX_WITH_SAFE(n) NOEX_WITH(n, ruby_safe_level) ++ + void +@@ -259,3 +264,3 @@ + rb_clear_cache_by_id(mid); +- body = NEW_METHOD(node, noex); ++ body = NEW_METHOD(node, NOEX_WITH_SAFE(noex)); + st_insert(RCLASS(klass)->m_tbl, mid, body); +@@ -4350,3 +4356,3 @@ + static VALUE +-rb_call0(klass, recv, id, argc, argv, body, nosuper) ++rb_call0(klass, recv, id, argc, argv, body, flags) + VALUE klass, recv; +@@ -4356,3 +4362,3 @@ + NODE *body; /* OK */ +- int nosuper; ++ int flags; + { +@@ -4363,2 +4369,3 @@ + TMP_PROTECT; ++ volatile int safe = -1; + +@@ -4382,3 +4389,3 @@ + ruby_frame->last_func = id; +- ruby_frame->last_class = nosuper?0:klass; ++ ruby_frame->last_class = (flags & NOEX_UNDEF)?0:klass; + ruby_frame->self = recv; +@@ -4446,3 +4453,2 @@ + PUSH_SCOPE(); +- + if (body->nd_rval) { +@@ -4466,5 +4472,12 @@ + ++ 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); ++ } + PUSH_VARS(); + PUSH_TAG(PROT_FUNC); +- + if ((state = EXEC_TAG()) == 0) { +@@ -4552,2 +4565,3 @@ + } ++ if (safe >= 0) ruby_safe_level = safe; + POP_TAG(); +@@ -4639,3 +4653,3 @@ + +- return rb_call0(klass, recv, id, argc, argv, body, noex & NOEX_UNDEF); ++ return rb_call0(klass, recv, id, argc, argv, body, noex); + } +@@ -6632,2 +6648,3 @@ + ID id, oid; ++ int safe_level; + NODE *body; +@@ -6674,2 +6691,3 @@ + data->oid = oid; ++ data->safe_level = NOEX_WITH_SAFE(0); + OBJ_INFECT(method, klass); +@@ -6694,2 +6712,3 @@ + data->oid = orig->oid; ++ data->safe_level = NOEX_WITH_SAFE(0); + OBJ_INFECT(method, obj); +@@ -6745,18 +6764,14 @@ + struct METHOD *data; +- int state; +- volatile int safe = ruby_safe_level; ++ int safe; + + Data_Get_Struct(method, struct METHOD, data); +- PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT); +- PUSH_TAG(PROT_NONE); +- if (OBJ_TAINTED(method) && ruby_safe_level < 4) { +- ruby_safe_level = 4; ++ if (OBJ_TAINTED(method)) { ++ safe = NOEX_WITH(data->safe_level, 4)|NOEX_TAINTED; + } +- if ((state = EXEC_TAG()) == 0) { +- result = rb_call0(data->klass,data->recv,data->id,argc,argv,data->body,0); ++ else { ++ safe = data->safe_level; + } +- POP_TAG(); ++ PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT); ++ result = rb_call0(data->klass,data->recv,data->id,argc,argv,data->body,safe); + POP_ITER(); +- ruby_safe_level = safe; +- if (state) JUMP_TAG(state); + return result; +@@ -6826,2 +6841,5 @@ + return INT2FIX(0); ++ case NODE_BMETHOD: ++ case NODE_DMETHOD: ++ return proc_arity(method); + default: --- patch-ruby16 ends here --- >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200510212139.j9LLdhS6068291>