iPhoneに期待してちょっと待ってたけど、ソフトバンクは7,280円からでemobileと比べるとちょっと割高感あるし、ドコモは期待できなさそうだしということで、iPod touchを買ってしまいましたw

EMONSTER+WMWifiRouterと組み合わせて使ってみたけど、なかなか快適。
※注: 見てたところが違ってたので、下のほうに追記してます。
パッと見て何が問題か理解できなかったのでソースを見てみる。
$ svn export http://svn.ruby-lang.org/repos/ruby/tags/v1_8_6_229/ v1_8_6_229 $ svn export http://svn.ruby-lang.org/repos/ruby/tags/v1_8_6_230/ v1_8_6_230 $ diff -d -r diff -d -r v1_8_6_229 v1_8_6_230 diff -d -r v1_8_6_229/ChangeLog v1_8_6_230/ChangeLog 0a1,4 > Fri Jun 20 18:24:18 2008 Nobuyoshi Nakada <nobu@ruby-lang.org> > > * string.c (rb_str_buf_append): should infect. > diff -d -r v1_8_6_229/string.c v1_8_6_230/string.c 6c6 < $Date: 2008-06-20 15:53:16 +0900 (金, 20 6月 2008) $ --- > $Date: 2008-06-20 18:24:53 +0900 (金, 20 6月 2008) $ 781c781,783 < return str_buf_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); --- > str_buf_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); > OBJ_INFECT(str, str2); > return str; diff -d -r v1_8_6_229/version.h v1_8_6_230/version.h 5c5 < #define RUBY_PATCHLEVEL 229 --- > #define RUBY_PATCHLEVEL 230
ソースコードの中で変わっているのは、strings.cのrb_str_buf_append()の内容だけ。
OBJ_INFECT()とはなんだろ?ということで、ruby.hを見ると
#define OBJ_INFECT(x,s) do {if (FL_ABLE(x) && FL_ABLE(s)) RBASIC(x)->flags |= RBASIC(s)->flags & FL_TAINT;} while (0)
という感じ。汚染フラグを伝染させるマクロな様子。なるほど。
で、rb_str_buf_append()がどこで使われているかというと…
$ cd v1_8_6_230 $ grep rb_str_buf_append * ChangeLog: * string.c (rb_str_buf_append): should infect. ChangeLog: * string.c (rb_str_buf_append): fixed unsafe use of alloca, array.c: rb_str_buf_append(result, sep); array.c: rb_str_buf_append(result, tmp); array.c: rb_str_buf_append(str, s); error.c: rb_str_buf_append(str, klass); error.c: rb_str_buf_append(str, exc); eval.c: rb_str_buf_append(str, rb_inspect(data->klass)); eval.c: rb_str_buf_append(str, rb_inspect(v)); eval.c: rb_str_buf_append(str, rb_inspect(data->recv)); eval.c: rb_str_buf_append(str, rb_inspect(v)); file.c: rb_str_buf_append(result, sep); file.c: rb_str_buf_append(result, tmp); hash.c: rb_str_buf_append(str, str2); hash.c: rb_str_buf_append(str, str2); hash.c: rb_str_buf_append(str, i); intern.h:VALUE rb_str_buf_append _((VALUE, VALUE)); re.c: rb_str_buf_append(source, v); string.c:rb_str_buf_append(str, str2) string.c: return rb_str_buf_append(str, str2);
む、結構いろんなところで使われているのね…
とりあえず脆弱性の原因としては、$SAFE=4とかのオブジェクトの汚染モデルをあてにしているプログラムで、意図しないところで汚染フラグが外れて困ることがあるよという認識でいいのかな?
見てたところがちょっと違ってました(汗
1.8.6-p228のChangeLogを見たら
Wed Jun 18 22:25:10 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
* array.c (ary_new, rb_ary_initialize, rb_ary_store,
rb_ary_aplice, rb_ary_times): integer overflows should be
checked. based on patches from Drew Yao <ayao at apple.com>
fixed CVE-2008-2726
* string.c (rb_str_buf_append): fixed unsafe use of alloca,
which led memory corruption. based on a patch from Drew Yao
<ayao at apple.com> fixed CVE-2008-2726
* sprintf.c (rb_str_format): backported from trunk.
* intern.h: ditto.
ということみたいなので、1.8.6-p227と1.8.6-p228の差分をみると関係ありそうなのは下記のところかな?
$ svn export http://svn.ruby-lang.org/repos/ruby/tags/v1_8_6_227/ v1_8_6_227
$ svn export http://svn.ruby-lang.org/repos/ruby/tags/v1_8_6_228/ v1_8_6_228
$ diff -d -r v1_8_6_227 v1_8_6_228 | lv
・
・
・
diff -d -r v1_8_6_227/array.c v1_8_6_228/array.c
・
・
・
> #define ARY_MAX_SIZE (LONG_MAX / sizeof(VALUE))
123c124
< if (len > 0 && len * sizeof(VALUE) <= len) {
---
> if (len > ARY_MAX_SIZE) {
296c297
< if (len > 0 && len * (long)sizeof(VALUE) <= len) {
---
> if (len > ARY_MAX_SIZE) {
360a362,364
> else if (idx >= ARY_MAX_SIZE) {
> rb_raise(rb_eIndexError, "index %ld too big", idx);
> }
369,371c373,374
< new_capa += idx;
< if (new_capa * (long)sizeof(VALUE) <= new_capa) {
< rb_raise(rb_eArgError, "index too big");
---
> else if (new_capa >= ARY_MAX_SIZE - idx) {
> new_capa = (ARY_MAX_SIZE - idx) / 2;
372a376
> new_capa += idx;
978a983,985
> if (len < 0 || len > ARY_MAX_SIZE) {
> rb_raise(rb_eIndexError, "index %ld too big", beg);
> }
2381c2388
< if (LONG_MAX/len < RARRAY(ary)->len) {
---
> if (ARY_MAX_SIZE/len < RARRAY(ary)->len) {
※lenがでかいとlen * sizeof(VALUE)とかnew_capa * (long)sizeof(VALUE)とかが負になる可能性がある
・
・
・
diff -d -r v1_8_6_227/string.c v1_8_6_228/string.c
6c6
・
・
・
782a776,778
> if (len < 0 || (capa+1) > LONG_MAX / 2) {
> rb_raise(rb_eArgError, "string sizes too big");
> }
※ rb_str_buf_append()関数の中で、
if (capa <= len) {
while (len > capa) {
capa = (capa + 1) * 2;
}
RESIZE_CAPA(str, capa);
}
とappend先のstrのバッファをリサイズしているところがあるが、
ここで先の(capa+1) > LONG_MAX / 2のチェックをしていないと
capa = (capa + 1) * 2が負になり、RESIZE_CAPA()がおかしくなる可能性。
Chumbyは通常Wi-Fi環境がないとwidgetを見ることすらできないのですが、 自作のswfをChumbyに表示したいだけならこんな感じで動かすことができます。
まずUSBメモリを用意してこんな感じでファイルを配置します。 自作のswfはhoge.swfと仮定しています。
$ ls -al total 128 drwxrwxrwx 1 yoggy yoggy 16384 6 22 01:17 ./ drwxrwxrwt@ 5 root admin 170 6 22 01:15 ../ -rwxrwxrwx 1 yoggy yoggy 62 6 22 01:13 debugchumby* -rwxrwxrwx 1 yoggy yoggy 17063 6 22 01:10 hoge.swf*
debugchumbyファイルの中身は、こんな感じのシェルスクリプトを記述しておきます。
$ cat debugchumby #!/bin/sh /usr/bin/chumbyflashplayer.x -i /mnt/usb/hoge.swf
次にこのUSBメモリをChumbyに刺して起動すると、スタートアップの画面が表示された後、 Chumbyはいきなりhoge.swfだけが再生される状態になります。
通常はChumbyを起動するとコントロールパネルのswfが再生されるのですが、 debugchumbyという名前のファイルがUSBメモリにあると、コントロールパネルが起動する前にこのファイルを実行する仕掛けが/etc/init.d/rcSに用意されています。 そこでdebugchubmyの中でむりやりhoge.swfを表示することで、 コントロールパネルを置き換えているような感じになります。
debugchumbyファイルとかの詳しい仕掛けについては、 起動時に実行される/etc/init.d/rcSの内容を参照してください。
…これでとりあえずはswfが再生できるかもしれないけど、よく考えたらChumbyはネットワークにつながってるところで使わないと、魅力が半減しちゃうような気がしないでもなかったりw
◆ tessy [あぁー]
◆ yoggy [ひょっとして買うタイミング間違えた?(汗]