free of free
gatling on libowfat with dietlibc
(続き)
バグりすぎだ!
たったの5分でうっかり2個もバグを発見し、さらに5分でなんだか修正できた気がするってのはそれなりに良い傾向なのかそれともすこぶる悪い傾向なのか。ええといや修正が正しいかどうかは実は確認してないので話半分にしておいてください。
面倒くさいのでDebianっぽいsrcを元に作業していますが、ええともしかして上流のHEADでは実は修正済みだったりしたのかしらん。でも調べるのも面倒くさいからもういいや。まあ使われていないコードの品質なんてこんなもんだよね・・・。
/server-status
実際問題としては少々ゴミが出るだけでクラッシュはおそらくしないだろうけど、それでも場合によっては機密情報漏洩の向きでexploit扱いになるんじゃなかろうか・・・。
--- orig/gatling-0.12/http.c +++ HEAD/gatling-0.12/http.c @@ -1596,9 +1596,9 @@ i=fmt_str(nh,"HTTP/1.0 200 OK\r\nServer: " RELEASE "\r\nContent-Type: text/html\r\nConnection: close\r\nContent-Length: "); i+=fmt_ulong(nh+i,l); i+=fmt_str(nh+i,"\r\n\r\n"); i+=fmt_str(nh+i,buf); - iob_addbuf_free(&h->iob,nh,strlen(nh)); + iob_addbuf_free(&h->iob,nh,i); h->keepalive=0; io_wantwrite(s); if (logging) {
きっとこのコードを書いた人はそのときちょっとばかり気が振れていたんだと思います。
anti-anti-DoS
いやいやいやいや。それDoS以前の問題だし。こっちはちょっとまじめに計算したら普通にexploitになる気がする・・・けどそっち向きには興味がないし面倒くさいので終了。
--- orig/gatling-0.12/connstat.c +++ HEAD/gatling-0.12/connstat.c @@ -38,9 +38,9 @@ struct connection* tmp; if ((*x)->last+60 < now || (*x)->connections <= max_requests_per_minute/10) { // had a minute of silence or very low volume -> remove tmp=*x; - x=&(*x)->next; + *x=(*x)->next; free(tmp); } else { /* halve connections count on record unless they exceed threshold */ if ((*x)->connections < max_requests_per_minute)
きっとこのコードを書いた人はそのときちょっとばかり気が急いていたんだと思います。
16bit UID/GID = obsolete
ケチってkernel側の実装を削ってしまっている場合。
まずdietlibcの側の実装がなぜか歯抜けで意味不明なので穴埋めしないと動きません。ええとsharedなdietlibcをする場合は dyn_syscalls.S にも書き足さないといけないはずだけど、どうせ使わないから無視。
--- orig/dietlibc-0.32/syscalls.s/setgroups32.S +++ HEAD/dietlibc-0.32/syscalls.s/setgroups32.S @@ -0,0 +1,5 @@ +#include "syscalls.h" + +#ifdef __NR_setgroups32 +syscall_weak(setgroups32,setgroups32,__libc_setgroups32) +#endif --- orig/dietlibc-0.32/syscalls.s/setresuid32.S +++ HEAD/dietlibc-0.32/syscalls.s/setresuid32.S @@ -0,0 +1,5 @@ +#include "syscalls.h" + +#ifdef __NR_setresuid32 +syscall_weak(setresuid32,setresuid32,__libc_setresuid32) +#endif
その上でgatling側で havesetresuid.h のあたりに下記の如きインチキを押し込めばおおむねだいたいソレっぽくなるかと。ただし当該の .h 自体に書き込んでもmake中に粉砕されてしまうのでそのあたりは適当に。
#define LIBC_HAS_SETRESUID #define uid_t uid32_t #define gid_t gid32_t #define setuid setuid32 #define setgid setgid32 #define geteuid geteuid32 #define setgroups setgroups32 #define setresuid setresuid32 #define setresgid setresgid32
で結局
Debianのパッケージが何か変だと思ったらdietできてないとか意味ないやん。いずれにしても少なくとも gatling <=0.12-2 で -A すると確実に危険というか自殺行為なので使わない方がいいと思います。とはいえ大抵は迅速に自殺完了する筈なので、本物の悪意が迫ってくるまで放置される(できる)ことはたぶん無い。気がする。
他にも /../ の挙動が謎いとか突っ込みどころは色々あるんだけど、とりあえずちゃんとdietしてコンパイルしたらwebfsdより縮んだからまあよしとしよう・・・。うん。
111009追記
だー。byte range への応答が後ろに1byte足りてない。しかも range が複数の時はあっているという間抜けさ加減。それ自体はなおしたけれどだんだん嫌になってきたので放棄。
というわけで今度は赤く薫るnginxにしてみた。おぉぉ・・・