Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

delegate が利用できないと きどうしてますか?

0 views
Skip to first unread message

Motoyuki Kasahara

unread,
Nov 10, 2000, 8:20:28 PM11/10/00
to
笠原です。
fj.comp.security にも投げて、Followup-To はそちらにしました。

* From: keis...@ocharake.org
* Message-ID: <3A0B7330...@ocharake.org>
> > 私も、freebsd.orgのセキュリティページ
> > http://home.jp.freebsd.org/cgi-bin/showmail/announce-jp/392
> > の内容をみて心配になっていたのですが、どうやら5.9より新しいバージョンを利
> > 用すれば大丈夫のように思えてきました。
>
> DeleGate のメーリングリストでも Version 6 以上では問題ないのに、
> まだ誤解されているとの投稿があったみたいですね。

まず、FreeBSD Security Advisory (FreeBSD SA) では、DeleGate のコー
ディングスタイルに対し、潜在的にセキュリティホールになる箇所がと
ても多く、ソースコードを一から書き直さない限り危険だろう、といっ
た指摘がありました。

DeleGate 6.x のソースをちょっと眺めた限りでは、私にもそう思えてき
ます。たとえば、6.1.20 の httpd.c の中から引用すると

| extern char *TIMEFORM_LS;
| static putDir(Conn,dirpath,tmp,fp,eol)
| Connection *Conn;
| char *dirpath;
| FILE *tmp,*fp;
| char *eol;
| { char line[1024];
| char file[2048];
| char iconbase[1024],*iconsrc,*iconalt;
| char pfile[2048];
| char path[1024];
| int size,time,isdir;
| char atime[128];

このように配列の長さを 1024 とか 128 とか、決め打ちで書いてること
が非常に多く、sprintf() 等でこの配列に書き込む際にちゃんと領域を
はみ出して書き込まないようにチェックしているのかどうか疑問に思
える箇所もかなりあります。これが FreeBSD SAの言う「潜在的なセキュ
リティホール」ではないかと思います。

ただ、これは、ソースを軽く眺め限りの話で、きちんと処理を追ったわ
けではありません。ですので、DeleGate が安全かどうかの疑問の一つ
として本当に大丈夫なの? ということがあります。

それから、たとえチェックをやっていたとしても、配列の長さを 1024,
128 といった形であちこちに書いてしまっていると、書き間違えたりす
ることはないんでしょうか。 1024 バイトを超えて書き込まないかどう
かチェックしていても、その配列の長さは実は char [256] だったとい
うようなミスが、このコーディングスタイルでは生みやすくないのかなぁ
という気もしなくもありません。

あと、「DeleGate 6 では大丈夫」という意見を私も聞いたことがある
のですが、本当だとしたらどういう対策をしたから大丈夫ということ
なんでしょうか。ひょっとしてそれは、randstack, randenv, randfd
が実装されたから、ということなんでしょうか。

randstack -- randomization range of stack base for security
randenv -- randomization range of environment variables base
randfd -- randomization range of client socket file-descriptor

ただ、これを使えば、先のような配列の使い方を多用をしていて
buffer overrun が起きても安心、なんでしょうか? 私には何とも
言えません。ただ、この機能を実装したことによって、セキュリティ
的に安全だったとしても、動作が安定するかどうかとはまた別の話と
いう気がします。

以上、DeleGate は安全か、ということに関しは、私には次のような
疑問があります。

* 配列の長さの決め打ちを多用しているけど、書き込み時の
buffer overrun チェックは十分やっているの?
* FreeBSD SA が DeleGate を危険と認識したのは、そうした決
め打ちの多用が原因なんじゃないの?
* たとえ書き込み時の長さのチェックはしていたとしても、ミス
は起きやすくないの?
* バージョン 6 では大丈夫っていう話は開発側の公式見解?
* バージョン 6 では大丈夫っていう話の根拠は randstack,
randenv, randfd を実装したから?
* randstack, randenv, randfd は、本当に「多数の潜在的なセ
キュリティホール」を解消できるものなの?

似たような疑問を持つ人が他にもいるのではないでしょうか。たぶん、
こうした疑問に答えが出ない限り、いつまで経っても危険視を肯定す
る意見が絶えず、また危険視を否定する側からは「まだ FreeBSD SA
の内容を信じているのか」といった話が出てきて、話が噛み合わない
状態が続くのではないかと思うんですが。
________________________________________________________________
笠原 基之(かさはら もとゆき)

UCHIDA Toshiaki

unread,
Nov 11, 2000, 2:45:09 AM11/11/00
to
"Motoyuki Kasahara" <m-ka...@sra.co.jp> wrote in message
news:8ui6ss$18t1$1...@sranhh.sra.co.jp...

> まず、FreeBSD Security Advisory (FreeBSD SA) では、DeleGate のコー
> ディングスタイルに対し、潜在的にセキュリティホールになる箇所がと
> ても多く、ソースコードを一から書き直さない限り危険だろう、といっ
> た指摘がありました。

Delegate って security hole が多そうな code もそうですし、無芸な cache の
file 配置とか、気色悪い make 方法とか、何よりも1つの binary にいろいろな
protocol の proxy を乗っけたりしていてゴテゴテしているとか、欠点が非常に多い
気がします。

確かに、NNTP cache server を何も考えずに立ち上げたいなんて時は手軽なので内田
もつかってはいるのですが、間違っても firewall で application gateway 用の
program としてつかうようなものではないでしょう。
--
内田 俊明 (UCHIDA,Toshiaki)

Hironobu Suzuki

unread,
Nov 11, 2000, 3:00:00 AM11/11/00
to

>>>>> "M" == Motoyuki Kasahara <m-ka...@sra.co.jp> writes:
In article <8ui6ss$18t1$1...@sranhh.sra.co.jp> m-ka...@sra.co.jp (Motoyuki Kasahara) writes:
M> ただ、この機能を実装したことによって、セキュリティ的に安全だったと
M> しても、動作が安定するかどうかとはまた別の話という気がします。

正解。

もっちょっとメタな観点から見ると「この手のSecurity Vulnerabilityの問題
はSoftware Qualityの問題のsubsetとして扱える、だからHigh Quality
Software Developmentで用いるような手法が本来は使える(はず)」なのですよ。

世界中を見回しても、まだまだソフトウェアプロセスからのアプローチぐらい
しか手をつけていないみたいだし、まだあまりこの分野の研究は進んでいない
ので、今、手をつければ、まさに早いもの勝ちだよ!誰かやってみる?

ひろのぶ

Kazuo Fox Dohzono

unread,
Nov 11, 2000, 3:00:00 AM11/11/00
to
堂園%今通信衛星の仕事をしてます.

いつも思うんですが, この手の buffer overrun 絡みの穴を作ってしまう人は

char foo[1024];

と書いた時点で心配にならないのでしょうか. 私なんかはこう書くとそれだけ
で心配になるので foo に対するアクセス制限方法をまず考えるのですけど…
(私の場合セキュリティという面ではなく, 純粋なソフトウェアの品質面での
話ですが).

# traditional な UNIX のソフトウェアにこういうのが散見されるのは UNIX
# 文化の悪い点でもある/あった, と思う.

In article <HIRONOBU.00...@h2np.h2np.suginami.removeme.tokyo.jp>
hiro...@h2np.suginami.removeme.tokyo.jp (Hironobu Suzuki) writes:

> 世界中を見回しても、まだまだソフトウェアプロセスからのアプローチぐらい
> しか手をつけていない

たとえば, 他にどのようなアプローチが考えられるのでしょうか. 検証の自動
化とか, そっちの方ですか?

--
Kazuo Fox Dohzono / doh...@hf.rim.or.jp

[12],(6,9),0,0,2

Murakami Hiroshi

unread,
Nov 12, 2000, 2:23:15 AM11/12/00
to

Kazuo Fox Dohzono wrote:

> 堂園%今通信衛星の仕事をしてます.
>
> いつも思うんですが, この手の buffer overrun 絡みの穴を作ってしまう人は
>
> char foo[1024];
>
> と書いた時点で心配にならないのでしょうか. 私なんかはこう書くとそれだけ
> で心配になるので foo に対するアクセス制限方法をまず考えるのですけど…
> (私の場合セキュリティという面ではなく, 純粋なソフトウェアの品質面での
> 話ですが).
>
> # traditional な UNIX のソフトウェアにこういうのが散見されるのは UNIX
> # 文化の悪い点でもある/あった, と思う.
>

C言語自身の設計の欠点だろうと思います。
つまり、本当の意味でのオブジェクトとしての「配列」は言語には備わっておらず、
実際にはアドレスで代用している。(変数の宣言のところで領域を確保するところ
では、一見配列風にみせていますが。)

Kazuo Fox Dohzono

unread,
Nov 12, 2000, 3:00:00 AM11/12/00
to
堂園です.

In article <3A0E4563...@ca2.so-net.ne.jp>
Murakami Hiroshi <nws...@ca2.so-net.ne.jp> writes:

> C言語自身の設計の欠点だろうと思います。

それは「セキュリティ (あるいは別の堅牢性) を要するプログラムに C を使
うのが間違い」という意見ですか?

# ま, それはそうかも.

Shinji KONO

unread,
Nov 12, 2000, 3:00:00 AM11/12/00
to
河野 真治@琉球大情報工学です。

In article <3A0E4563...@ca2.so-net.ne.jp> ,
Murakami Hiroshi <nws...@ca2.so-net.ne.jp> writes
>> char foo[1024];
>C言語自身の設計の欠点だろうと思います。

そうじゃなくって...
printf/scanf が、生成される文字列の長さを予測出来ない
というライブラリの設計のまずさが原因だと思います。

char foo[1024]; と書きたくないなら書かなければ良いだけですよね。
そう書かなければならないとかいうなら言語に責任があると思うんだけど、
そうではないでしょう?

なので、White Smith の方がいいとかいっていた人もいたような気がする。
---
Shinji KONO @ Information Engineering, University of the Ryukyus,
PRESTO, Japan Science and Technology Corporation
河野真治 @ 琉球大学工学部情報工学科,
科学技術振興事業団さきがけ研究21(機能と構成)

Motoyuki Kasahara

unread,
Nov 12, 2000, 3:00:00 AM11/12/00
to
笠原です。
すみません、ちょっと訂正します。

(自分で Followup-To: を fj.comp.security に向けておいてなんですが、
訂正ということで、もとの fj.os.bsd.freebsd にも投げておきます。)

* From: m-ka...@sra.co.jp
* Message-ID: <8ui6ss$18t1$1...@sranhh.sra.co.jp>


> まず、FreeBSD Security Advisory (FreeBSD SA) では、DeleGate のコー
> ディングスタイルに対し、潜在的にセキュリティホールになる箇所がと
> ても多く、ソースコードを一から書き直さない限り危険だろう、といっ
> た指摘がありました。

この部分ですがFreeBSD SA を読み返したところ、「一から書き直さない
限り危険」と解釈できる記述はなく、さすがに大袈裟でした。実際には、

FreeBSD-SA-00:04.delegate.asc:
| Unfortunately no simple fix is available - the problems with the
|delegate software are too endemic to be fixed by a simple patch.

といった表現になっています。
「潜在的なセキュリティホールが多数」という点はこの文書の中に

| Unfortunately it is written in a very insecure style, with
| potentially dozens of different exploitable buffer overflows

といった表現があります。
失礼しました。
________________________________________________________________
笠原 基之(かさはら もとゆき)

Kazuo Fox Dohzono

unread,
Nov 12, 2000, 3:00:00 AM11/12/00
to
堂園です.

In article <1078.97...@rananim.ie.u-ryukyu.ac.jp>
ko...@ie.u-ryukyu.ac.jp (Shinji KONO) writes:

> char foo[1024]; と書きたくないなら書かなければ良いだけですよね。
> そう書かなければならないとかいうなら言語に責任があると思うんだけど、
> そうではないでしょう?

char foo[1024]; が悪いわけではないですよね. それで充分である (それなり
のチェックが行われているとかの) 保証があるなら.

末尾にターミネイタやチェックサムなどがある場合は pool しなければその正
当性はわかりませんが, その途中でやはり「何らかの事情によって定められた
長さ」を越えたなら invalid なデータとして破棄するのが普通ですよね (ま
たは, 次のスタートマークらしき場所から処理するとか).

それをある程度自動でやらせたい (人為ミスを混入させたくない) 場合に C
だとちょっと…というのは, まあわかる意見ではあります.

Hironobu Suzuki

unread,
Nov 13, 2000, 3:00:00 AM11/13/00
to

>>>>> "K" == Kazuo Fox Dohzono <doh...@hf.rim.or.jp> writes:
In article <8uk594$73k$1...@netnews.rim.or.jp> doh...@hf.rim.or.jp (Kazuo Fox Dohzono) writes:
K> たとえば, 他にどのようなアプローチが考えられるのでしょうか. 検証の
K> 自動化とか, そっちの方ですか?

もっと広くソフトウェア品質向上のための理論/技法の大半が適用可能だと僕
は思っています。

学術的にもプラクティカルにも、まだまだセキュリティを前提としたソフトウェ
ア品質の理論は位置づけや体系化されていないので研究するなら今がチャンス
です。
ひろのぶ

Kazuo Fox Dohzono

unread,
Nov 13, 2000, 3:00:00 AM11/13/00
to
堂園です.

In article <HIRONOBU.00...@h2np.h2np.suginami.removeme.tokyo.jp>
hiro...@h2np.suginami.removeme.tokyo.jp (Hironobu Suzuki) writes:

> K> たとえば, 他にどのようなアプローチが考えられるのでしょうか. 検証の
> K> 自動化とか, そっちの方ですか?
>
> もっと広くソフトウェア品質向上のための理論/技法の大半が適用可能だと僕
> は思っています。

ああ, そうですね.

ついプログラマ的な発想をしてしまいましたけど, 仕様通りの動作をするソフ
トウェアがあり, 本来期待される動作をすべてうまくこなしたとしても, それ
が堅牢かどうか (これも広義には品質でしょうけど) はまた一段上の話ですね.

> 学術的にもプラクティカルにも、まだまだセキュリティを前提としたソフトウェ
> ア品質の理論は位置づけや体系化されていないので研究するなら今がチャンス
> です。

仕様を満たすソフトウェア作成の話と分けて, 「セキュリティを前提とした仕
様決定」の部分で独立になるかな.

SAKAI Kiyotaka

unread,
Nov 13, 2000, 8:58:24 PM11/13/00
to
>> In article <8umi2e$ofl$1...@netnews.rim.or.jp>, doh...@hf.rim.or.jp (Kazuo Fox Dohzono) writes:

> char foo[1024]; が悪いわけではないですよね. それで充分である (それなり
> のチェックが行われているとかの) 保証があるなら.

> 末尾にターミネイタやチェックサムなどがある場合は pool しなければその正
> 当性はわかりませんが, その途中でやはり「何らかの事情によって定められた
> 長さ」を越えたなら invalid なデータとして破棄するのが普通ですよね (ま
> たは, 次のスタートマークらしき場所から処理するとか).

> それをある程度自動でやらせたい (人為ミスを混入させたくない) 場合に C
> だとちょっと…というのは, まあわかる意見ではあります.

http://www.trl.ibm.co.jp/projects/security/ssp/

とか。
--
酒井 清隆 (E-mail: ksa...@kso.netwk.ntt-at.co.jp)

Yasushi Shinjo

unread,
Nov 13, 2000, 11:22:32 PM11/13/00
to
新城@筑波大学情報です。こんにちは。
DeleGate を使っています。

In article <8ui6ss$18t1$1...@sranhh.sra.co.jp>
m-ka...@sra.co.jp (Motoyuki Kasahara) writes:

> 笠原です。


> まず、FreeBSD Security Advisory (FreeBSD SA) では、DeleGate のコー
> ディングスタイルに対し、潜在的にセキュリティホールになる箇所がと
> ても多く、ソースコードを一から書き直さない限り危険だろう、といっ
> た指摘がありました。

これに対しての DeleGate の作者の佐藤豊さんの答えは、次の場所
にあります。

http://www.delegate.org/mail-lists/archive/delegate/9110-9120
http://www.delegate.org/mail-lists/delegate-en/636
http://www.delegate.org/delegate/Manual.htm#defense

> DeleGate 6.x のソースをちょっと眺めた限りでは、私にもそう思えてき
> ます。

たしかに DeleGate には、一見、スタック・オーバーフローを起さ
せることができるように見えますが、実際に、こうやったら起きる
とか、DeleGate 内蔵の検出機能にひっかからなかったという話は、
見つかっていません。元の FreeBSD-SA-00:04 は、バグがつぶされ
てから、3ヶ月もたった後で、出てきたもののようです。

> あと、「DeleGate 6 では大丈夫」という意見を私も聞いたことがある
> のですが、本当だとしたらどういう対策をしたから大丈夫ということ
> なんでしょうか。

詳しくは、上で示した原文を見て欲しいのですが、DeleGate 5 と
6 では、DNS 関連のコードが IPv4 対応も含めて大きく変わってい
て、バグの指摘は、DeleGate 5.9 のものにらしい(具体的にどの
バージョンが問題なのかはバグを指摘している方で明示していない)
ということです。

> る意見が絶えず、また危険視を否定する側からは「まだ FreeBSD SA
> の内容を信じているのか」といった話が出てきて、話が噛み合わない
> 状態が続くのではないかと思うんですが。

私は、FreeBSD SA のあやふやで、古い指摘より、DeleGate の著者
を信じます。

具体的なバグの指摘があったのが、去年の11月で、バグを潰すの
は、即座に行われたのですが、その後、3ヵ月たってから、古いバー
ジョンに対するSecurity Advisory がでたり、さらにそれから、9ヵ
月たってからfj に記事が出たりと、この辺りの情報の伝わり方や
速度についても、研究ネタが埋まっているかもしれません。
ロミオとジュリエットから、人間変わっていないということなので、
一般的に解くのは難しいのでしょうけど、バグ情報の信憑性のよう
な話ならなんとかなるかもしれません。

> それから、たとえチェックをやっていたとしても、配列の長さを 1024,
> 128 といった形であちこちに書いてしまっていると、書き間違えたりす
> ることはないんでしょうか。 1024 バイトを超えて書き込まないかどう
> かチェックしていても、その配列の長さは実は char [256] だったとい
> うようなミスが、このコーディングスタイルでは生みやすくないのかなぁ
> という気もしなくもありません。

それは、そうでしょうね。普通の人は、真似をしない方がよいコー
ディング・スタイルです。

\\ 新城 靖 (しんじょう やすし) \\
\\ 筑波大学 電子・情報       \\

Kazuo Fox Dohzono

unread,
Nov 14, 2000, 1:19:36 AM11/14/00
to
堂園です.

In article <20001114105...@kso.netwk.ntt-at.co.jp>
SAKAI Kiyotaka <ksa...@kso.netwk.ntt-at.co.jp> writes:

> http://www.trl.ibm.co.jp/projects/security/ssp/
>
> とか。

この手のはランタイム時の話になっちゃいますよね. 静的な方面でのロジック
チェッカのようなものがいいと思いませんか?

# いつぞやの仕様記述言語の話になってくるのかなあ.

Kazuo Fox Dohzono

unread,
Nov 14, 2000, 3:00:00 AM11/14/00
to
堂園です.

In article <8ui6ss$18t1$1...@sranhh.sra.co.jp>
m-ka...@sra.co.jp (Motoyuki Kasahara) writes:

> このように配列の長さを 1024 とか 128 とか、決め打ちで書いてること
> が非常に多く、sprintf() 等でこの配列に書き込む際にちゃんと領域を
> はみ出して書き込まないようにチェックしているのかどうか疑問に思
> える箇所もかなりあります。これが FreeBSD SAの言う「潜在的なセキュ
> リティホール」ではないかと思います。

C における固定長の (単純な) 配列についてですが, 潜在的に

char foo[MAX_FOO];

も同じ問題を持つと思います. で, 私はチェック時に (1024 といった) 即値
はもちろん, MAX_FOO も用いず

#define elements_of(x) ((sizeof (x))/(sizeof (x)[0]))

を用いて

if (elements_of (foo) <= ++wi)
...;

のようにしています. これならば決め打ち即セキュリティホールということに
はならないはずです (malloc/realloc にしても同様のチェックはどこかで必
要なはずですよね).

これを (我ながら例外がないかどうか半信半疑で) 使い始めてしばらくは良かっ
たのですが,

void
func (foo_t foo[N]) /* N に意味はありませんが, 「実はそうなんだ」という気持ちで */
{
unsigned i;
for (i = 0; i < elements_of (foo); i++)
...;
}

としてしまったことがあるのを白状しておきます.

# 他にもありますかね?

Kazuo Fox Dohzono

unread,
Nov 15, 2000, 3:00:00 AM11/15/00
to
堂園です. もう一点.

In article <8ur0un$lkf$1...@netnews.rim.or.jp>


doh...@hf.rim.or.jp (Kazuo Fox Dohzono) writes:

> In article <8ui6ss$18t1$1...@sranhh.sra.co.jp>
> m-ka...@sra.co.jp (Motoyuki Kasahara) writes:
>

> > このように配列の長さを 1024 とか 128 とか、決め打ちで書いてること
> > が非常に多く、sprintf() 等でこの配列に書き込む際にちゃんと領域を
> > はみ出して書き込まないようにチェックしているのかどうか疑問に思
> > える箇所もかなりあります。これが FreeBSD SAの言う「潜在的なセキュ
> > リティホール」ではないかと思います。

における sprintf ですが, 書式が固定であれば実は要求される領域の最大長
はほとんどの場合で事前にわかるのではないかと思います. %c, %d, %x 辺り
はもちろん, %f も 308+α (符号や小数点など) くらいですよね (%s は考え
どころでしょうけど).

snprintf を使うのも手ですが, 利用される format と長さの組を定義するファ
イルと, 事前にチェックするプログラムを用意しておいて, ランタイム時に失
敗がないようにしておくのもいいのではないでしょうか.

# malloc/realloc を使って順次領域を伸しながら書式化するライブラリがあっ
# てもいいかも. char *mprintf() とか.

Motoyuki Kasahara

unread,
Nov 15, 2000, 8:35:03 PM11/15/00
to
笠原です。

* From: y...@is.tsukuba.ac.jp
* Message-ID: <YAS.00No...@kirk.is.tsukuba.ac.jp>


> > DeleGate 6.x のソースをちょっと眺めた限りでは、私にもそう思えてき
> > ます。
>
> たしかに DeleGate には、一見、スタック・オーバーフローを起さ
> せることができるように見えますが、実際に、こうやったら起きる
> とか、DeleGate 内蔵の検出機能にひっかからなかったという話は、
> 見つかっていません。元の FreeBSD-SA-00:04 は、バグがつぶされ
> てから、3ヶ月もたった後で、出てきたもののようです。

具体的にどういうものか知りませんが、「DeleGate 内蔵の検出機能」の
お陰で実際にはオーバーフローを起こさせない仕組みになっているんでしょ
うか。それとも、たんに「これまで一度もそういった報告はない」と言っ
ているだけでなんでしょうか。

どちらかによって、意味合いはずいぶん変わってくると思います。

> 私は、FreeBSD SA のあやふやで、古い指摘より、DeleGate の著者
> を信じます。

DeleGate に関する FreeBSD SA の発行の経緯に不満があるのは分かり
ますが、"with potentially dozens of different exploitable buffer
overflows" という部分の記述は、依然として事実です。

たとえ FreeBSD SA のこの部分の記述だけを判断理由にしたとしても、
DeleGate のバイナリパッケージを FreeBSD では配布しないという方針
は妥当だと私は思います。

もし、内蔵の検出機能によってこの記述を否定できるのなら、それを具
体的に説明しないことには、「FreeBSD SA の指摘はあやふや」とだけ非
難してもあまり説得力を感じません。

FreeBSD でバイナリパッケージを配ろうが配るまいが関係ないかも知れ
ませんが、FreeBSD やその他の OS のユーザの一部に混乱があるのは事
実だと思います。私も含めて。
________________________________________________________________
笠原 基之(かさはら もとゆき)

Yoshiki Kataoka

unread,
Nov 16, 2000, 11:41:50 AM11/16/00
to
片岡です。

どんな経緯で、その話になったのかは預かり知りませんが...
(知ることができない、ではなく、関知する意志がありません)

それは、MAX_FOO を使うか elements_of なるマクロを使うか、
という問題ではなく、単に foo への直接アクセスが行われる
範囲の問題ではないでしょうか。

static char foo[MAX_FOO];
ptrdiff_t get_elements_of_foo()
{
return MAX_FOO;
}


Kazuo Fox Dohzono

unread,
Nov 17, 2000, 3:00:00 AM11/17/00
to
堂園です.

境界を越えてアクセスするような例外を処理可能な言語には敵わないんでしょ
うけど.

In article <8v12jn$fip$1...@news01bd.so-net.ne.jp>
"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> writes:

> それは、MAX_FOO を使うか elements_of なるマクロを使うか、
> という問題ではなく、単に foo への直接アクセスが行われる
> 範囲の問題ではないでしょうか。

プログラマが即値や MAX_FOO のような情報 (ここでいう“情報”には“識別
子 MAX_FOO が配列 foo の大きさを*確かに*表しているか”も含みます) を
プログラミング時に得るには, 記憶に頼るか, その定義個所を見に行く動作が
必要です (識別子は foo だけではない). いい道具 (editor) があれば大した
手間ではないのかもしれませんが.

私はそういった手間を嫌ってアクセスチェックの為のコードが抜けてしまう場
合もあるのではないかと思っています (elements_of は一つのマクロの挙動と
foo がスコープ内であることをプログラマが知っていればいい).

そもそも foo に対するアクセスチェックコードにおいて, プログラマが意識
しなければならないのは foo の要素数であり, 即値やそれに代わる識別子で
はないはずです (当初はマクロではなく一々タイプしていました). 私は慣れ
てしまいましたが, elements_of() は思いの外便利ですよ[*].

> static char foo[MAX_FOO];
> ptrdiff_t get_elements_of_foo()
> {
> return MAX_FOO;
> }

これは MAX_FOO を使う場合と同種の問題を持っている気がします, というと
言い過ぎかしら.

# [*]:
#
# 限られたケースかも知れませんが, const な配列 c[] とそれに呼応する変
# 数 v[] があるとき, v[elements_of (c)] という使い方も出来ます. 設定ファ
# イルから値を読む場合などに
#
# const char * const cmds[] = {
# "foo_val",
# "bar_val",
# ...
# };
# value_t v[elements_of (cmds)];
#
# とか.

Yoshiki Kataoka

unread,
Nov 20, 2000, 3:00:00 AM11/20/00
to
片岡です。

> 境界を越えてアクセスするような例外を処理可能な言語には敵わないんでしょ
> うけど.

配列の毎回レンジチェックのようなことが
必要なときは「そういう関数を作ればよい」、
必要でないときに「余計なコストを節約できる」、
がCの思想だと私は思っていますから、
この点が他の言語に対するウイークポイントとは感じていません。

void CharKaku(char *p, ptrdiff_t i, char a, ptrdiff_t max, jmp_buf jb)
{
if( i < 0 || max <= i ) longjmp(jb, 1);
*(p + i) = a;
}

逆に、他の言語に毒されて「必要な関数」を作らないことがあるのでは?

つまり、決めうち配列を仮に malloc に置き換えたとしても、
原因がここにある限り、何も改善しないばかりか、
malloc のコストだけを空費することになると思います。

# 必要なときは「そういう言語を作ればよい」
# なるほど、世界中でやってますね

> プログラマが即値や MAX_FOO のような情報 (ここでいう“情報”には“識別
> 子 MAX_FOO が配列 foo の大きさを*確かに*表しているか”も含みます) を
> プログラミング時に得るには, 記憶に頼るか, その定義個所を見に行く動作が
> 必要です (識別子は foo だけではない). いい道具 (editor) があれば大した
> 手間ではないのかもしれませんが.

# 私も同じことを言ってしまったようなのでバツが悪いですが

定義場所を見に行かなければ情報が得られない、
という時点で何かが違っているのでは?

char foo[MAX_FOO];

void DamenaRei(void)
{
fgets(foo, MAX_FOO, stdin);
}

void MottoSunaoni(char *p, ptrdiff_t max)
{
fgets(p, (int)max, stdin);
}

どうしてもグローバル変数が必要な場合や
性能面の制約が非常に強い場合を除いて
引数で渡す方が望ましいと思います。

つまり、foo の定義に責任を持つモジュールを探す旅に出るより、
すぐ上のモジュールまでバケツリレーで伝わっている情報から絞り込んで
聞けるのならその方がよいと思うのです。

# もっとも、max を貰っておいて使わないというミスは
# これでも完全には防げませんが。


> 私はそういった手間を嫌ってアクセスチェックの為のコードが抜けてしまう場
> 合もあるのではないかと思っています (elements_of は一つのマクロの挙動と
> foo がスコープ内であることをプログラマが知っていればいい).

こういうことですよね。

void Jousou(void)
{
char foo[MAX_FOO];
MottoSunaoni(foo, elements_of(foo), stdin);
}

> > static char foo[MAX_FOO];
> > ptrdiff_t get_elements_of_foo()
> > {
> > return MAX_FOO;
> > }
>

> これは MAX_FOO を使う場合と同種の問題を持っている気がします, というと
> 言い過ぎかしら.

いや、仰るとおり。
寝ぼけていたようでお恥ずかしい。(自己嫌悪)

> # 限られたケースかも知れませんが, const な配列 c[] とそれに呼応する変
> # 数 v[] があるとき, v[elements_of (c)] という使い方も出来ます. 設定ファ
> # イルから値を読む場合などに
> #
> # const char * const cmds[] = {
> # "foo_val",
> # "bar_val",
> # ...
> # };
> # value_t v[elements_of (cmds)];
> #
> # とか.

なるほど。

しかし foo_val が [0] で bar_val が [1] という時点で
また要素番号のいやらしさにつながりませんか?


Yasushi Shinjo

unread,
Nov 20, 2000, 11:45:35 PM11/20/00
to
新城@筑波大学情報です。こんにちは。

セキュリティというのは、100%に近づけようとすると急激にコ
ストがかかります。暗号も100%解けないというのは、真性乱数
を使うものしかなくて、他のものは解けます。安全性は、結局、攻
撃とか解読に要するコストを大きくすることで、攻撃や解読から得
られる利益を相対的に小さくしようという話です。

In article <8uvdk7$pgq$1...@sranhh.sra.co.jp>


m-ka...@sra.co.jp (Motoyuki Kasahara) writes:
> 笠原です。

> 具体的にどういうものか知りませんが、「DeleGate 内蔵の検出機能」の
> お陰で実際にはオーバーフローを起こさせない仕組みになっているんでしょ
> うか。それとも、たんに「これまで一度もそういった報告はない」と言っ
> ているだけでなんでしょうか。

「検出」というのは、「防止」ではありません。DeleGate は、バッ
ファ・オーバーフローを起すことがあります。しかし、それが即座
にシステムに侵入されるということにはつながりません。

DeleGate の攻撃検出機能の説明は、次の場所にあります。

http://www.delegate.org/delegate/Manual.htm#defense

バッファ・オーバーフローを起すと、多くの場合、攻撃を受けたサー
バは、クラッシュします。DeleGate には、クラッシュが起きると、
管理者に電子メールで通知して、さらに、そのクラッシュの原因と
なった接続先を一時的に拒否します。

「多くの場合」、クラッシュすると書きましたが、これがどうして
100%ではないかというと、乱数を使っているからです。
DeleGate は、スタックの底を乱数で変えています。この結果、C
言語の auto 変数の番地が、ランダムに変わることになります。バッ
ファ・オーバーフローで、auto 変数に怪しいコードを送り込むの
に成功したとしても、その番地はランダムに変わります。その怪し
いコードに制御を飛ばすためには、リターン・アドレスを、そのラ
ンダムな番地に書き換えないといけないわけですが、それはランダ
ムなわけで、非常に難しいわけです。

でもランダムなので、100%ではありません。何回かに1回は、
成功するでしょう。でも、その前に、多くの場合は、検知機能の働
きで攻撃の活動が見つかってしまうし、クラッシュして再起動した
としても、今度は同じ手では攻撃に成功しません。

念のために付け加えておくと、DeleGate は、この機能に依存して
バッファ・オーバーラン対策を手抜きしているわけではありません。
バッファ・オーバーラン対策は、人間技でやっていて、今まで人間
技で見つかったものは、全部潰されているということです。「人間
技」に頼るのは、まあ、何なんで、その部分を機械的にできればい
いというのは、その通りです。Java で書くとかね。DeleGate は、
移植性を重んじているソフトウェアなので、そのうち Java で書き
直されるという話は、、、どうなんでしょうね。

> DeleGate に関する FreeBSD SA の発行の経緯に不満があるのは分かり
> ますが、"with potentially dozens of different exploitable buffer
> overflows" という部分の記述は、依然として事実です。

はい。そうです。

> たとえ FreeBSD SA のこの部分の記述だけを判断理由にしたとしても、
> DeleGate のバイナリパッケージを FreeBSD では配布しないという方針
> は妥当だと私は思います。

はい。バイナリ・パッケージを配布しないというのは、SA が出て
も出なくても、もともとやらない方がよいことだと思います。実際、
作者も、DeleGate の配布を、オリジナルからの ftp による配布だ
けに制限したいと言っています。2年ほど前に作者に会った時に、
FreeBSD の CD にDeleGate が入っていると言ったら、驚いていま
した。作者は、知らなかったみたいです。

> もし、内蔵の検出機能によってこの記述を否定できるのなら、それを具
> 体的に説明しないことには、「FreeBSD SA の指摘はあやふや」とだけ非
> 難してもあまり説得力を感じません。
>
> FreeBSD でバイナリパッケージを配ろうが配るまいが関係ないかも知れ
> ませんが、FreeBSD やその他の OS のユーザの一部に混乱があるのは事
> 実だと思います。私も含めて。

それで、バッファ・オーバーフローをを狙う攻撃を防ぐ方法ですが、
スタックの底のランダム化よりも効果があるのは、スタックを実行
禁止にすることです。そのような FreeBSD 用のパッチは、どこか
に落ちてないでしょうか。それを当ると、FreeBSD のユーザは、安
心して DeleGate を使えるようになります。

スタックの実行禁止は、パッチというよりは、それがデフォルトと
いうのが、今の世の中にあっているんでしょうね。

Kazuo Fox Dohzono

unread,
Nov 20, 2000, 11:44:37 PM11/20/00
to
堂園です.

In article <8vbdne$56a$1...@news01bf.so-net.ne.jp>
"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> writes:

> 配列の毎回レンジチェックのようなことが
> 必要なときは「そういう関数を作ればよい」、
> 必要でないときに「余計なコストを節約できる」、
> がCの思想だと私は思っていますから、
> この点が他の言語に対するウイークポイントとは感じていません。

ランタイム時に行うか事前に行うかの違いはあれ, range check は必須なはず
ですよね (入力が MAX に満たないという条件も広義の range check でしょう).

> void CharKaku(char *p, ptrdiff_t i, char a, ptrdiff_t max, jmp_buf jb)
> {
> if( i < 0 || max <= i ) longjmp(jb, 1);
> *(p + i) = a;
> }

私はこういうコードは見通しが悪くなるのであまり好きじゃないです. やると
したら関数の直前でマクロを定義して, 使い終わったらさっさと undef する
かな.

> しかし foo_val が [0] で bar_val が [1] という時点で
> また要素番号のいやらしさにつながりませんか?

#ifdef vdef
vdef (foo_val)
vdef (bar_val)
vdef (baz_val)
#else

enum {
#define vdef(x) e_ ## x,
#include __FILE__
#undef vdef
e_NVALS
};

const char * const names[] = {
#define vdef(x) # x,
#include __FILE__
#undef vdef
};

value_t vals[elements_of (names)];

evaluate (vals[e_foo_val]);

#endif /* vdef */

まあ enum を使うなら e_NVALS が使えるますけど.

Motoyuki Kasahara

unread,
Nov 21, 2000, 9:29:33 PM11/21/00
to
笠原です。こんにちは。

> セキュリティというのは、100%に近づけようとすると急激にコ
> ストがかかります。暗号も100%解けないというのは、真性乱数
>を使うものしかなくて、他のものは解けます。安全性は、結局、攻
> 撃とか解読に要するコストを大きくすることで、攻撃や解読から得
> られる利益を相対的に小さくしようという話です。

う~ん、今回の DeleGate の話に限って言えば、ここまでメタな話ま
で遡る必要はないのでは...。危険性の多いコーディングスタイルを
変えずに続けているという実情に原因があるわけですから。


> 「多くの場合」、クラッシュすると書きましたが、これがどうして
> 100%ではないかというと、乱数を使っているからです。
> DeleGate は、スタックの底を乱数で変えています。

なるほど。あのようなコーディングでも安全だ、という根拠は結局や
はり randstack, randenv, randfd にある、ということなんですよね。

randstack のことは既に私が前に書いた記事
<8ui6ss$18t1$1...@sranhh.sra.co.jp> でも触れてますが、私が疑問なの
は「randstack があれば本当にスタック上のコードを実行される危険
はないのか?」ということです。

ここで私が言っているのは、「ランダムだから○○回に一回は偶然当
たる」ということではなくて、もっと高い確率で当てることは不可能
なのか、ということなんですが、どうなんでしょう。

新城さんは開発者を信じている、ということなんですよね。


> 念のために付け加えておくと、DeleGate は、この機能に依存して
> バッファ・オーバーラン対策を手抜きしているわけではありません。
> バッファ・オーバーラン対策は、人間技でやっていて、今まで人間
> 技で見つかったものは、全部潰されているということです。「人間

あのコーディングは、セキュリティだけでなく品質を犠牲にして書き
込み先の領域の長さのチェックをさぼっているわけですから、やっぱ
り「手抜き」だと思います。(人のコードをそこまでキッパリ言うの
は忍びないんですけど。)


> > DeleGate に関する FreeBSD SA の発行の経緯に不満があるのは分かり
> > ますが、"with potentially dozens of different exploitable buffer
> > overflows" という部分の記述は、依然として事実です。
>
> はい。そうです。

: (中略)


> はい。バイナリ・パッケージを配布しないというのは、SA が出て
> も出なくても、もともとやらない方がよいことだと思います。実際、

「危険だからバイナリの配布はしない方が良い」ということですか?
でも新城さんは、危険性に関しては否定されてきたわけですよね。
「バイナリの配布はしないほうが良い」というのは、「危険だから使
わない方が良い」というのとは違うんでしょうか。(?_?)
________________________________________________________________
笠原 基之(かさはら もとゆき)

Takuya ASADA

unread,
Nov 22, 2000, 2:34:53 AM11/22/00
to
笠原さん>
> 「バイナリの配布はしないほうが良い」というのは、「危険だから使
> わない方が良い」というのとは違うんでしょうか。(?_?)

「バイナリの配布」は、古いバージョンが使われ続ける可能性が高い
という点を危惧しているんではないかと、私は思いました。


あさだ たくや

Kazuo Fox Dohzono

unread,
Nov 22, 2000, 3:00:00 AM11/22/00
to
堂園です.

In article <86itpgt...@pooh.isoternet.org>
Takuya ASADA <as...@pooh.isoternet.org> writes:

同一のソースコードだからといって同一のバイナリが生成されるとは限らない,
つまりコンパイラオプションなどによって実行時のスタックフレームが異なる
場合があるのに, バイナリ配布はその機会を無くしているということではない
でしょうか. クラッカーがバイナリ配布をターゲットにするなら, その配布版
の穴を探せばいいわけで.

Yoshiki Kataoka

unread,
Nov 22, 2000, 6:01:48 PM11/22/00
to
片岡です。

> ランタイム時に行うか事前に行うかの違いはあれ, range check は必須なはず
> ですよね (入力が MAX に満たないという条件も広義の range check でしょう).

その点に異議はないですが、毎回というのが引っかかるんです。
具体的に「毎回」とはどなたも仰っていないようですが、
「他の言語」がそれを含意していると感じるのです。

> > void CharKaku(char *p, ptrdiff_t i, char a, ptrdiff_t max, jmp_buf jb)
> > {
> > if( i < 0 || max <= i ) longjmp(jb, 1);
> > *(p + i) = a;
> > }
>
> 私はこういうコードは見通しが悪くなるのであまり好きじゃないです. やると
> したら関数の直前でマクロを定義して, 使い終わったらさっさと undef する
> かな.

「他の言語では」としきりに言う人たちって、
言語側でのレンジチェックがこれと等価コードになっていることを
わかって言っているんでしょうかね。

Cで「subscript out of range」と表示するコードを自分で用意せよと言われ、
_iob が使える環境やメッセージテキストの読み手のスキルを決めうちする
コードを自分で書かされるに及んで、やっと何かに気がつきかけたあたりで
「これだからCは」と脱線を始める...

「他の言語」って、レンジチェックにとらわれずに、本筋の処理を
すんなり書けるから気持ちいいんじゃなかったんですかね。
そのための longjmp って、そんなに見通しを悪くするんでしょうか。

> #ifdef vdef
> vdef (foo_val)
> vdef (bar_val)
> vdef (baz_val)
> #else
>
> enum {
> #define vdef(x) e_ ## x,
> #include __FILE__
> #undef vdef
> e_NVALS
> };
>
> const char * const names[] = {
> #define vdef(x) # x,
> #include __FILE__
> #undef vdef
> };
>
> value_t vals[elements_of (names)];
>
> evaluate (vals[e_foo_val]);
>
> #endif /* vdef */
>
> まあ enum を使うなら e_NVALS が使えるますけど.

うわ、強烈。 #include の再帰ですか。

私だったら構造体でマップを作るかな。

#define E(x) { #x, &x ## _ram, x ## _func },

配列の他にリストや木という手があり動的な管理にも応用が利きますし、
enum で switch - case する代わりに関数ポインタにしておけば
エントリを追加/削除するときのロジック変更が不要です。


しかし、こんな場面では elements_of もよさそうですね。

struct Q
{
char *buff;
ptrdiff_t max, read, write;
};

char rbuff[1024], sbuff[256];
struct Q rQ = { rbuff, elements_of(rbuff) };
struct Q sQ = { sbuff, elements_of(sbuff) };


ポインタでこうやる選択もありますけど、

struct Q
{
char *begin, *end;
char *read, *write;
};

char rbuff[1024], sbuff[256];
struct Q rQ = { rbuff, *(&rbuff + 1), rbuff, rbuff };
struct Q sQ = { sbuff, *(&sbuff + 1), sbuff, sbuff };

循環カウントの関数が応用きかなくなりますから。
ptrdiff_t CyclicCount(ptrdiff_t i, ptrdiff_t max);


MAEDA Atusi (前田敦司)

unread,
Nov 23, 2000, 2:36:06 AM11/23/00
to ma...@cc.tsukuba.ac.jp
"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> writes:

> 「他の言語では」としきりに言う人たちって、
> 言語側でのレンジチェックがこれと等価コードになっていることを
> わかって言っているんでしょうかね。

等価にはならないでしょう。コンパイラがrange checkを理解してれば、それ
なりの最適化ができます。(ループの入り口で1回だけとか。) また、アクセス
のたびに関数呼び出しが起きたりもしません。(Cにはinline 関数無いし、マ
クロじゃ困るし...)

前田敦司

Yoshiki Kataoka

unread,
Nov 23, 2000, 5:34:45 PM11/23/00
to
片岡です。


> 等価にはならないでしょう。コンパイラがrange checkを理解してれば、それ
> なりの最適化ができます。(ループの入り口で1回だけとか。)

例えば次のようなモジュールを他言語で書いた場合、
必要でないチェックをコンパイラはどのように見つけるのですか。

ptrdiff_t CyclicCount(ptrdiff_t i, ptrdiff_t max)

{
if(++i == max)
{
i = 0;
}
return i;
}

struct Q
{
char *buff;
ptrdiff_t max, read, write;
};

void WriteQ(struct Q *p, char data)
{
p->buff[p->write] = data;
p->write = CyclicCount(p->write, p->max);
}

配列のレンジ・チェックは局所的な最適化では
扱えない種類の問題だと私は思っています。

# 作ろうとしているアプリケーション全体を理解する
# コンパイラでもあれば別でしょうけど、
# それじゃこっちがクビになってしまう


> また、アクセス
> のたびに関数呼び出しが起きたりもしません。(Cにはinline 関数無いし、マ
> クロじゃ困るし...)

最適化を持ち出すなら、inline はCにもありそうですね。


MAEDA Atusi (前田敦司)

unread,
Nov 23, 2000, 11:02:11 PM11/23/00
to ma...@cc.tsukuba.ac.jp
"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> writes:

> > 等価にはならないでしょう。コンパイラがrange checkを理解してれば、それ
> > なりの最適化ができます。(ループの入り口で1回だけとか。)
>
> 例えば次のようなモジュールを他言語で書いた場合、
> 必要でないチェックをコンパイラはどのように見つけるのですか。

常に最適化できるわけではありませんがそれなりにはできます。等価ではあり
ません。

> > また、アクセス
> > のたびに関数呼び出しが起きたりもしません。(Cにはinline 関数無いし、マ
> > クロじゃ困るし...)
>
> 最適化を持ち出すなら、inline はCにもありそうですね。

モジュール化をあきらめてinline展開できる場合もあるでしょうが、他の言語
のように常にinlineでチェックされるわけではないでしょう。等価ではありま
せん。

前田敦司

Kazuo Fox Dohzono

unread,
Nov 23, 2000, 11:36:22 PM11/23/00
to
堂園です.

私が「境界を越えてアクセスするような例外を処理可能な言語には敵わない」
としたのはその厳密性においてです. たとえば

In article <8vhj54$aif$1...@news01df.so-net.ne.jp>
"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> writes:

> > > void CharKaku(char *p, ptrdiff_t i, char a, ptrdiff_t max, jmp_buf jb)

これにしても五つものパラメータの入力を毎回プログラマに要求するわけです.
書かなくて済むならそれだけ誤る個所が減るわけで, それに越したことはない
と思います.

> 「他の言語では」としきりに言う人たちって、
> 言語側でのレンジチェックがこれと等価コードになっていることを
> わかって言っているんでしょうかね。

というわけで等価だとは思えません.

# そういう言語と同じことをしようとすると効率ガタ落ちなのがはっきりわか
# る例ですね.

> 「他の言語」って、レンジチェックにとらわれずに、本筋の処理を
> すんなり書けるから気持ちいいんじゃなかったんですかね。

それもあると思います.

> そのための longjmp って、そんなに見通しを悪くするんでしょうか。

多分, 示されたコードに setjmp が見えないのが私にそう思わせているのでは
ないでしょうか. 示されたコードだけでそれを用いたモジュールが正しく動作
するかは依然として不明なわけで.

Yoshiki Kataoka

unread,
Nov 26, 2000, 3:00:00 AM11/26/00
to
片岡です。


同じ言語でさえコンパイラのバージョンが違えば
「等価」ではなくなりますからね。悪うございました。

私はそんなことではなく、
結局同じことだと言いたかったのです。

もし、配列に対する不必要なレンジチェックを言語側で
自動回避する効果的な手法をご存知でしたら
お聞かせ願えませんか。(自動回避するための条件分岐が
毎回レンジチェックと大差ないのはだめです)

# そんなに即答しなくても
# 1週間やそこら平気で待ってますよ


Yoshiki Kataoka

unread,
Nov 26, 2000, 3:00:00 AM11/26/00
to
片岡です。


> > > > void CharKaku(char *p, ptrdiff_t i, char a, ptrdiff_t max, jmp_buf
jb)
>
> これにしても五つものパラメータの入力を毎回プログラマに要求するわけです.
> 書かなくて済むならそれだけ誤る個所が減るわけで, それに越したことはない
> と思います.

これは確かに。 私もそう思います。

ただ、それは厳密性を実現できる/できない、ではありませんよね。
Cでも、必要なら「安全な配列システム」を構造体と関数群で作れます。
それの安全性が、どのくらいのテストを経ているかでほぼ決まる
という意味でコンパイラ自体やインタプリタ自体と結局は同じでしょう。

だから私は、この点がCのウイークポイントとは思えないのです。
ただ、私がいま「安全な配列システム」を作れ、と言われたら
template は欲しくなりそうですが、これはCにはありませんね。
(なくてもトンズラこく程でもないですが)


> というわけで等価だとは思えません.

他の方にもコメントしましたが、どうも「等価」とか「完全」のような
表現を *ここで* 使ったのが間違いだったようです。

私はバイナリのビット単位での同一性を言ったのではなく、
配列に対する不必要なレンジチェックを言語処理系が
自動回避できる場合は少なすぎると言おうとしただけです。


> # そういう言語と同じことをしようとすると効率ガタ落ちなのがはっきりわか
> # る例ですね.

すみません、「そういう言語」という部分がわかりません。


> > そのための longjmp って、そんなに見通しを悪くするんでしょうか。
>
> 多分, 示されたコードに setjmp が見えないのが私にそう思わせているのでは
> ないでしょうか. 示されたコードだけでそれを用いたモジュールが正しく動作
> するかは依然として不明なわけで.

これは <setjmp.h> に対する経験値でしょう。
ちゃんと向き合ってみると捨てたものでもありませんよ。

Kazuo Fox Dohzono

unread,
Nov 26, 2000, 3:00:00 AM11/26/00
to
堂園です.

In article <8vqgsn$eg9$1...@news01cg.so-net.ne.jp>
"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> writes:

> ただ、私がいま「安全な配列システム」を作れ、と言われたら
> template は欲しくなりそうですが、これはCにはありませんね。

何処かでも書きましたが, template は ISO/IEC 9899:1999 で輸入して欲しい
機能の一つではありました. 辻褄あわせが大変かもしれませんけど.

> 配列に対する不必要なレンジチェックを言語処理系が
> 自動回避できる場合は少なすぎると言おうとしただけです。

人為ミスが有り得るという状態と無いという状態には大きな隔たりがあると思
います.

> > > void CharKaku(char *p, ptrdiff_t i, char a, ptrdiff_t max, jmp_buf jb)

にはプログラマが意識しなければならないもう一つの大きなパラメータ“型情
報”がありますが, これも出来れば機械任せにしたいですし.

話変わって効率. バッファサイズが 2^n であるという情報が静的に得られる
ならば cyclic バッファインデックスの更新は単なる論理積になりますよね.
つまり idx の値域が 0 以上 N (= 2^n) 未満ならば

if (N <= ++idx)
idx = 0;

idx = (++idx) & N-1;

となりますし, range check も

if (idx & ~(N-1))
...;

となりますが (バッファサイズを 2^n として #define する場合が多いのはこ
れを狙っているからだと思います), C で 汎用的に書いてしまうと (open な
どの引数でバッファサイズを与えるようにすると) これも不可能になります.

欲しいですよね, template :-)

> > # そういう言語と同じことをしようとすると効率ガタ落ちなのがはっきりわか
> > # る例ですね.
>
> すみません、「そういう言語」という部分がわかりません。

私の頭の中には具体的には C++, 抽象的には検証論的な書き方の出来る言語が
あります (後者は前者を使ってある程度構築可能かも知れない).

C++ について実は実装に明るくないのですけど, jmp_buf を添字更新の度にス
タックに積むようなことにはならないのではないでしょうか (少なくともそれ
を避けるコーディングは可能なのでは).

> > 多分, 示されたコードに setjmp が見えないのが私にそう思わせているのでは
> > ないでしょうか. 示されたコードだけでそれを用いたモジュールが正しく動作
> > するかは依然として不明なわけで.
>

> これは <setjmp.h> に対する経験値でしょう。
> ちゃんと向き合ってみると捨てたものでもありませんよ。

setjmp/longjmp は今の仕事でも使っています.

# goto もそれなりに使います :-)

MAEDA Atusi (前田敦司)

unread,
Nov 26, 2000, 12:00:29 PM11/26/00
to ma...@cc.tsukuba.ac.jp
Path: hagi.cc.tsukuba.ac.jp!not-for-mail
Lines: 79
Message-ID: <m37l5qa...@maedapc.cc.tsukuba.ac.jp>
References: <8udcsa$1oip$1...@news.cnet-sc.ne.jp> <8udgqf$3tl$1...@nw042.infoweb.ne.jp> <8udimr$48u$1...@nw042.infoweb.ne.jp> <8udlbt$1s24$1...@news.cnet-sc.ne.jp> <3A0B7330...@ocharake.org> <8ui6ss$18t1$1...@sranhh.sra.co.jp> <8ur0un$lkf$1...@netnews.rim.or.jp> <8v12jn$fip$1...@news01bd.so-net.ne.jp> <8v2ts2$oi7$1...@netnews.rim.or.jp> <8vbdne$56a$1...@news01bf.so-net.ne.jp> <8vd1b9$94$1...@netnews.rim.or.jp> <8vhj54$aif$1...@news01df.so-net.ne.jp> <m3em03w...@maedapc.cc.tsukuba.ac.jp> <8vk5sn$lu4$1...@news01di.so-net.ne.jp> <m3em02j...@maedapc.cc.tsukuba.ac.jp> <8vqgso$eg9$2...@news01cg.so-net.ne.jp>
NNTP-Posting-Host: maedapc.cc.tsukuba.ac.jp
Mime-Version: 1.0 (generated by SEMI 1.13.7 - "Awazu")
Content-Type: text/plain; charset=ISO-2022-JP
X-Trace: hagi.cc.tsukuba.ac.jp 975257716 26747 130.158.72.55 (26 Nov 2000 16:55:16 GMT)
X-Complaints-To: ne...@cc.tsukuba.ac.jp
NNTP-Posting-Date: 26 Nov 2000 16:55:16 GMT
User-Agent: Nana-gnus/6.13.12 SEMI/1.13.7 (Awazu) CLIME/1.13.6
(中ノ庄) Emacs/20.5 (i386-vine-linux-gnu) MULE/4.1 (AOI)
Cache-Post-Path: maedapc.cc.tsukuba.ac.jp!500@localhost
X-Cache: nntpcache 2.3.3 (see http://www.nntpcache.org/)
Xref: hagi.cc.tsukuba.ac.jp fj.comp.lang.c:5382 fj.comp.security:969
X-Cache: nntpcache 2.3.3 (see http://www.nntpcache.org/)

"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> writes:

> 私はそんなことではなく、
> 結局同じことだと言いたかったのです。

「結局同じ」ではないです。

> もし、配列に対する不必要なレンジチェックを言語側で
> 自動回避する効果的な手法をご存知でしたら
> お聞かせ願えませんか。(自動回避するための条件分岐が
> 毎回レンジチェックと大差ないのはだめです)

以下のような単純な例を考えます。

void foo(char a[], int b, int c)
{
int i;
for (i = b; i < c; i++) {
a[i] = 0;
}
}

で、配列のrange checkをするJavaのような言語では、コンパイラがrange
checkを特別扱いするので、チェックをループの外に追い出すことができます。
(Javaの場合、上では 0 <= b と c <= a.length をチェックすれば良い。)
また、上のコンパイル時に呼び出し元もわかっているようなときには、range
checkをコンパイル時にすべて済ませてしまえる場合もあるでしょう。

Cの関数やマクロではそうは行きません。
上のかわりに、

typedef struct {
char *body;
size_t length;
} array_t;

void foo(array_t *a, int b, int c)
{
int i;
for (i = b; i < c; i++) {
CharKaku(a->body, i, 0, a->length, error);
}
}
と書いたとします。

induction variableや不等式に関する超強力な推論機能をもつCのコンパイラ
が仮にあったとして(実際には難しいと思いますが)、

CharKakuのチェック


if( i < 0 || max <= i ) longjmp(jb, 1);

をループの前に追い出して、
if (b < 0) longjmp(error, 1);
if (a->length <= c - 1) longjmp(error, 1);
としたとすると、エラー時にlongjmpが呼ばれるタイミング(呼ばれたときのi
の値や配列の内容)が変ってしまいますから、このような最適化は許されませ
ん。つまりCで、「必要な機能はユーザが作れる」というアプローチでは、
range check機能を元々持つ言語より効率が悪くなります。

配列のrange checkの最適化については、

V. Markstein, J. Cocke, and P. Markstein.
Optimization of range checking.
Proceedings of the SIGPLAN '82 Symposium on Compiler Construction,
114-119, June 1982.

R. Gupta.
A fresh look at optimizing array bound checking.
Proceedings of the ACM SIGPLAN '90
Conference on Programming Language Design and Implementation, 272-282,
June, 1990.

Priyadarshan Kolte and Michael Wolfe.
Elimination of redundant array subscript range checks.
Proceedings of the ACM SIGPLAN '95 Conference on Programming Language
Design and Implementation, 270-278, June 1995.

とかをご覧ください。

前田敦司

MAEDA Atusi (前田敦司)

unread,
Nov 26, 2000, 12:28:12 PM11/26/00
to ma...@cc.tsukuba.ac.jp
"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> writes:

> 私はそんなことではなく、
> 結局同じことだと言いたかったのです。

「結局同じ」ではないんです。

> もし、配列に対する不必要なレンジチェックを言語側で
> 自動回避する効果的な手法をご存知でしたら
> お聞かせ願えませんか。(自動回避するための条件分岐が
> 毎回レンジチェックと大差ないのはだめです)

以下のような単純な例を考えます。

void foo(char a[], int b, int c)
{
int i;
for (i = b; i < c; i++) {
a[i] = 0;
}
}

で、配列のrange checkをするPascal, Ada, Javaのような言語では、コンパイ
ラがrange checkを特別扱いするので、チェックをループの外に追い出すこと
ができます。(Javaの場合、上では 0 <= b と c <= a.length をチェックすれ


ば良い。) また、上のコンパイル時に呼び出し元もわかっているようなときに
は、range checkをコンパイル時にすべて済ませてしまえる場合もあるでしょ
う。

Cの関数やマクロではそうは行きません。上のかわりにCで、

typedef struct {
char *body;
size_t length;
} array_t;

jmp_buf error;

void foo(array_t *a, int b, int c)
{
int i;
for (i = b; i < c; i++) {
CharKaku(a->body, i, 0, a->length, error);
}
}
と書いたとします。

induction variableや不等式に関する超強力な推論機能をもつCのコンパイラ
がたとえ仮にあったとしても、CharKakuのチェック


if( i < 0 || max <= i ) longjmp(jb, 1);

をループの前に追い出して、
if (b < 0) longjmp(error, 1);
if (a->length <= c - 1) longjmp(error, 1);

とすることはできません。

エラー時にlongjmpが呼ばれるタイミング(呼ばれたときのi の値や配列の内容)
が変ってしまいますから、このような最適化は許されません。

また、コンパイル時にrange errorを見つけることもできないでしょう(コンパ
イル時にlongjmpを呼び出すわけにもいかないでしょうから)。

結局のところ、CharKakuをループの中に書くと、ループの中で毎回チェックす
るコードを出さざるを得ないと思います。

###

常にチェックするCharKakuに加えて、「ループ用に上下限だけチェックするマ
クロ」とかを用意し、ループ本体ではチェックなしの配列アクセスをするよう
にすれば、Javaなどと同等の効率が得られますが、これは(間違いの危険が増す
ことを別としても)CharKakuと「等価」とはとても呼べないと思います。

###

配列のrange checkの最適化については、

V. Markstein, J. Cocke, and P. Markstein.
Optimization of range checking.
Proceedings of the SIGPLAN '82 Symposium on Compiler Construction,
114-119, June 1982.

R. Gupta.
A fresh look at optimizing array bound checking.
Proceedings of the ACM SIGPLAN '90
Conference on Programming Language Design and Implementation, 272-282,
June, 1990.

Priyadarshan Kolte and Michael Wolfe.
Elimination of redundant array subscript range checks.
Proceedings of the ACM SIGPLAN '95 Conference on Programming Language
Design and Implementation, 270-278, June 1995.

とかをご覧ください。上のような単純な場合以外の最適化も出てきます。

前田敦司

Yasushi Shinjo

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
新城@筑波大学情報です。こんにちは。

バイナリ配布ですが、

In article <8vfb2d$2rqf$1...@sranhh.sra.co.jp>
m-ka...@sra.co.jp (Motoyuki Kasahara) writes:
> 笠原です。こんにちは。


>> はい。バイナリ・パッケージを配布しないというのは、SA が出て
>> も出なくても、もともとやらない方がよいことだと思います。実際、
> 「危険だからバイナリの配布はしない方が良い」ということですか?
> でも新城さんは、危険性に関しては否定されてきたわけですよね。

> 「バイナリの配布はしないほうが良い」というのは、「危険だから使
> わない方が良い」というのとは違うんでしょうか。(?_?)

バイナリ配布しない方が良い、一番重要な理由は、バイナリ配布し
てしまうと、どうしても古くなってしまう、つまり、古いバグが修
正されないまま残っているということがあるということです。
DeleGate でも sendmail でも apache でも何でもそうですが、古
いバージョンの物の中には、実際にバグが在ることがはっきり分かっ
ているものがあります。最新のものにもバグはいるでしょうが、古
いものは潰されています。古いバグを突くような攻撃は、最新のも
のには通用しません。

DeleGate は、毎日のように更新されています。バグを報告すると、
セキュリティ面で重要なものなら、即座に更新されます。もちろん、
毎日追っ掛をしないといけないというわけではなくて、自分が使っ
ている機能の中で、重要そうなバグ・フィックスが出た時に更新す
ればいいわけです。情報収集には、メーリング・リストに入るのが
普通です。

In article <86itpgt...@pooh.isoternet.org>
Takuya ASADA <as...@pooh.isoternet.org> writes:

> 「バイナリの配布」は、古いバージョンが使われ続ける可能性が高い
> という点を危惧しているんではないかと、私は思いました。
> あさだ たくや

はい。さらに、バイナリ配布、特に CD-ROM だと、バグを潰したと
いう情報が伝わらないということがあります。

バイナリ配布の利用者は、バイナリをコピーして終りで、メーリン
グ・リストがあっても、なかなか入ろうとはしないでしょう。バイ
ナリ配布用のバイナリをコンパイルする人は、自分が作ったバイナ
リに重大な問題が見つかった時、バイナリをコピーしていった人に
連絡する義務があると思います。しかし実際には、そういう義務を
果たせる人は、そんなには多くはないと思います。Sun
Microsystems とか BSDI とか Red Hat といった会社は、できるで
しょうが、個人のボランティア・ベースでは、難しいでしょう。と
なると、義務が果たせない以上、「バイナリ配布をしない」という
のが責任のある行動だと思います。

あと、DeleGate 固有の話としては、バイナリ配布だと管理者のメー
ル・アドレスが正しく設定されない危険が高いということあります。
DeleGate は、コンパイル時に管理者のメール・アドレスを指定す
る必要があるのですが、これは意図的です。前の記事に書いたよう
に、DeleGate は外部からの攻撃を検知すると管理者に連絡の電子
メールを送るようになっています。管理者がそのメールを読むこと
は、DeleGate の運用上不可欠です。

ところが、バイナリ配布だと、管理者のアドレスはユニバーサルな
ものになります。root とか webmaster とか。バイナリをインストー
ルして使う人も、ドキュメントを読まずに適当に入れると、管理者
のメール・アドレスが必要だとは気が付かないかもしれません。も
ちろん、DeleGate のドキュメントには、バイナリ配布の DeleGate
を使う時にどんなアドレスを設定すればよいかは書かれていません。
ということは、バイナリ配布用のバイナリをコンパイルした人は、
別途ドキュメントを整備しないといけないわけです。こういうドキュ
メントの整備は、コンパイル時に1回やればいいという意味ではバ
グの通知よりは簡単ですが、手間が掛るものです。

というわけで、DeleGate は、ある時からバイナリ配布に対抗して、
管理者のメール・アドレスを起動時にも必ず指定しないといけない
ようになったのでした。作者は、この辺りの人間の性質をわかって
います。バイナリ配布を禁止してもやる人は出てくるし、ドキュメ
ントを読まないで実行する人も出てくるわけです。

FreeBSD のバイナリで、DeleGate の管理者はどうなっているでしょ
うか? それに関するドキュメントは、どこにありますか?

Yasushi Shinjo

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
新城@筑波大学情報です。こんにちは。

In article <8vfb2d$2rqf$1...@sranhh.sra.co.jp>
m-ka...@sra.co.jp (Motoyuki Kasahara) writes:
> 笠原です。こんにちは。
> 新城さんは開発者を信じている、ということなんですよね。

まあ、そういうことです。この辺り、たとえば、Unix の開発者の
一人、Ken Thompsonの ACM チューリング賞の記念講演でも、こん
な話が出ています。ソフトウェアの信頼性は、最後は作った人を信
用できるかという話になると。

http://www.acm.org/classics/sep95/

> > DeleGate は、スタックの底を乱数で変えています。
> なるほど。あのようなコーディングでも安全だ、という根拠は結局や
> はり randstack, randenv, randfd にある、ということなんですよね。

いいえ。DeleGate は、スタックの底のランダム化で安全性を保っ
ているのではありません。それは、単に補助的なものです。未知の
バグ、未来のバグに対するものです。DeleGate の安全性は、「人
間技」でバグを見つけて潰していることによっています。

> あのコーディングは、セキュリティだけでなく品質を犠牲にして書き
> 込み先の領域の長さのチェックをさぼっているわけですから、やっぱ
> り「手抜き」だと思います。(人のコードをそこまでキッパリ言うの
> は忍びないんですけど。)

DeleGate に、外からの攻撃にさらされる所には、手抜きはありま
せん。ローカルの DeleGate の管理者が起動時に長い引数を指定し
てバッファ・オーバーフローさせることはないだろう、DeleGate
5.X では named が RFC で規定された以上の長いホスト名を返すこ
とはないはずだ(6.X では修正済)という部分で、チェックをしてい
ない所はあります。それ以外のもので、怪しい遠隔からの攻撃で送
られてくる文字列を受ける所は、バッファが溢れないように人間技
で注意深く書かれています。コンスタントが生で書かれていても、
そうです。

別に #define を使っていても、スタック・オーバーフローは起き
る時には起きるわけです。定数名を間違えたら終りです。DeleGate
は、定数の使い方は作者が一人で作っているので、一貫した使い方
になっています。ですから、定数が生で入っていても、大丈夫なん
です。

人間技ではなくて、安心するには、前の記事ではスタックを実行禁
止にするという話を書きました。その他に、コンパイラの技でスタッ
ク・オーバーフローを検出するというのもあります。

http://www.cse.ogi.edu/DISC/projects/immunix/StackGuard/
http://immunix.org/

StackGuard は、gcc に手を入れて作られたコンパイラです。
StackGuard でコンパイルしたプログラムを実行すると、スタック
の戻り番地の所にカナリア語が置かれます。リターンする時に、カ
ナリアが死んでいれば、スタックが壊されていると判断してクラッ
シュします。

1年ほど前、かなり特殊な場合にしか問題にはならないのですが、
この StackGuard に問題が見つかりました。この問題は、既に潰さ
れています。新しい StackGuard にこの問題はありません。

http://lwn.net/1999/1111/a/stackguard.html

どんな攻撃に弱かったかというと、まず、スタック上の ポインタ
変数を書き換え、そのポインタの先のリターン・アドレスを攻撃す
るというものです。こうなると、1点だけ壊されるので、カナリア
が生きていても、リターン・アドレスが壊されている可能性がある
わけです。

StackGuard は、戻り番地を乱数で暗号化するという方法で解決し
ました。単純な戻り番地をスタックに積むのではなくて、乱数と
XOR したものを積みます。関数から戻る時には、乱数と XOR した
アドレスに戻ります。

というわけで、StackGuard で DeleGate をコンパイルして使うと
いうのも、スタックを実行禁止にする事の次によい方法です。

Kazuo Fox Dohzono

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
堂園%出張中です.

In article <m3puji8...@maedapc.cc.tsukuba.ac.jp>


ma...@cc.tsukuba.ac.jp (MAEDA Atusi (前田敦司)) writes:

> void foo(char a[], int b, int c)
> {
> int i;
> for (i = b; i < c; i++) {
> a[i] = 0;
> }
> }

> (Javaの場合、上では 0 <= b と c <= a.length をチェックすれば良い。)

C だと「または, c <= b」も入りますよね. “配列の”range check ではない
ですけど.

> induction variableや不等式に関する超強力な推論機能をもつCのコンパイラ
> がたとえ仮にあったとしても

このような推論機能を持つコンパイラにはどのようなものがあるのでしょうか
(C でも, C でなくても). 入手が容易でそういう方面の話が勉強できそうな本
とかありませんか? 洋書でもいいです.

Motoyuki Kasahara

unread,
Nov 27, 2000, 10:25:48 PM11/27/00
to
笠原です。こんにちは。

> バイナリ配布しない方が良い、一番重要な理由は、バイナリ配布し
> てしまうと、どうしても古くなってしまう、つまり、古いバグが修
> 正されないまま残っているということがあるということです。
> DeleGate でも sendmail でも apache でも何でもそうですが、古
> いバージョンの物の中には、実際にバグが在ることがはっきり分かっ
> ているものがあります。

ようするに、これは DeleGate に限った話ではないわけですね。

ただ、現状では Sendmail, Apache, BIND といった、外部からの攻撃
にも耐えなければならないような用途のソフトウェアも含めて、
FreeBSD や Linux の distribution の多くでバイナリが配布すること
が一般的になっているのはご存じかと思います。

この現状を踏まえた上で、やっぱりそれでもバイナリの配布は止めた
ほうが良いかどうかというのは、興味深い議論ではあるとは思うので
すが、ちょっと話が広がり過ぎるように思います。

お尋ねしておいて申し訳ないんですが、私はそこまでは議論の対象に
するつもりはないです。新城さんの意見は理解しました。


> DeleGate は、毎日のように更新されています。バグを報告すると、
> セキュリティ面で重要なものなら、即座に更新されます。

で、DeleGate に限った話じゃなく一般的な話かと思えば、ここから
は DeleGate 固有の話なんですよね。必要とあれば一般論を挟むこと
は構いませんが、どうもこれまで DeleGate 固有の話と一般論が噛み
合っていないような気がします。

もう少し両者を切り分けて、双方の関連付けをはっきりさせるという
か、一般論を持ち出すならその意図を明確にして頂けると分かりやす
いです。

失礼ですが、どうも DeleGate 固有の事情を無視して、必要もないの
に一般論を持ち出して、その一般論としての結論を DeleGate 固有の
議論に無理に当てはめているような印象さえ持ってしまいます。

これまでだと他には、randstack (*1) や StackGuard (*2) の話とか、
「セキュリティというものは...」と切り出してきたとき (*1) とか。
それぞれは価値ある情報を含んでいたりもしますが、議論に対しては
すこし混乱を招くものであったと思います。もちろん、これは新城さ
んの狙いではないと思いますけれど。

*1: <YAS.00No...@kirk.is.tsukuba.ac.jp>
*2: <YAS.00No...@kirk.is.tsukuba.ac.jp>

# ところで、更新されていると言っても、6.1.20 が出てから一月経ち
# ますよね。以前はそれこそ毎日バージョンが上がってた気がするん
# ですけど。:-D


> FreeBSD のバイナリで、DeleGate の管理者はどうなっているでしょ
> うか? それに関するドキュメントは、どこにありますか?

あえて直接は書きませんが、

http://www.freebsd.org/ports/net.html
http://www.jp.freebsd.org/www.freebsd.org/ports/net.html
http://www.jp.freebsd.org/www.freebsd.org/ja/ports/net.html

のいずれかから `delegate' を探して maintainer あるいは保守担当
者のところを見て下さい。2 番目は 1 番目のページの日本のミラー、
3 番目は日本語版、という説明でいいのかな?
________________________________________________________________
笠原 基之(かさはら もとゆき)

Motoyuki Kasahara

unread,
Nov 29, 2000, 3:00:00 AM11/29/00
to
笠原です。こんにちは。

> いいえ。DeleGate は、スタックの底のランダム化で安全性を保っ
> ているのではありません。それは、単に補助的なものです。未知の
> バグ、未来のバグに対するものです。DeleGate の安全性は、「人
> 間技」でバグを見つけて潰していることによっています。

見つかったバグの対処を迅速にするだけが、安全性ではないですよね。
未来に対するバグの配慮も安全性の一環でしょう。

未来のバグとなりうる、コーディングの危険性が FreeBSD SA という
形で指摘されていますし、開発者もこのことは認識しているようです。
なのに、「これまでに指摘されたバグは潰しているから安全です」と
いう過去にだけ言及しているのでは、配慮が十分とは思えません。


> DeleGate に、外からの攻撃にさらされる所には、手抜きはありま
> せん。

えー-、それは、ここにきて明かされる衝撃の新事実です。
チェックしているとは知りませんでした。

で、ちゃんとチェックしている外からの攻撃に晒される部分って、具
体的に何処なんでしょう。それとドキュメントにちゃんと書いてある
んでしょうか。ユーザが作者の予想の範囲を超えた部分も外からの攻
撃に晒してしまったら、危険だと思います。

# 私が最初の記事 <8ui6ss$18t1$1...@sranhh.sra.co.jp> で引用したのは、
# httpd.c なんですが、このファイルに書いてある関数は、外からの危
# 険に晒される部分ではないんでしょうか。httpd.c と言う名前からし
# て外気に晒される所かと思って選んだのですが。


> 人間技ではなくて、安心するには、前の記事ではスタックを実行禁
> 止にするという話を書きました。その他に、コンパイラの技でスタッ
> ク・オーバーフローを検出するというのもあります。

> というわけで、StackGuard で DeleGate をコンパイルして使うと
> いうのも、スタックを実行禁止にする事の次によい方法です。

StackGuard のオーバーフロー検出機能は、やるべきチェックをやって
ないソフトウェアを救うためのものじゃなくて、あくまでチェックをやっ
た上で補助的に使うものですよね。

つまり、StackGuard のようなものがあろうとなかろうと、DeleGate が
やるべきチェックをやっているかどうかは、遥かに問題です。
「StackGuard が使うのが良い方法」と簡単に言い切るのは、その議論
が済んだ後じゃないですか? (私との議論の主題のほうを先にしろ、と
いうわけじゃなくて)
________________________________________________________________
笠原 基之(かさはら もとゆき)

Motoyuki Kasahara

unread,
Nov 29, 2000, 3:00:00 AM11/29/00
to
笠原です。

> 別に #define を使っていても、スタック・オーバーフローは起き
> る時には起きるわけです。定数名を間違えたら終りです。DeleGate
> は、定数の使い方は作者が一人で作っているので、一貫した使い方
> になっています。ですから、定数が生で入っていても、大丈夫なん
> です。

いくらなんでも、話の運びに無理があると思います。

まず、「#define を使っていても起きるものは起きる」からといって、
使って効果があるかないかは、まったく別の話です。

# 取りつけても死亡事故は起きるのだから、車にエアバックは付けな
# い、というのは正しいですか?

DeleGate の randstack も、まさにそういう予想外の危機のためのも
の、という事ではなかったのでしょうか。


もう一つ。作者が一人なのは、一貫性の面で多少優位がある *かも知
れません* が、だからといって「大丈夫」とまで言い切れる根拠がど
こにあるのでしょうか。

DeleGate はソースコードの量も大きく、また数年に渡ってソースコー
ドは頻繁に更新されてきました。機能も次々に追加していって、拡張
されていきましたよね。そんな状況で、一人で一貫性を維持していく
ことが、実際のところ長所になり得ているなどとは、誰にも言い切れ
ないんじゃないでしょうか。

開発者が複数いた場合は、逆にチェックの目もそれだけ行き届く、と
いう長所も考えられます。
________________________________________________________________
笠原 基之(かさはら もとゆき)

Yasushi Shinjo

unread,
Nov 29, 2000, 3:00:00 AM11/29/00
to
新城@筑波大学情報です。こんにちは。

In article <8vv8js$1r3s$1...@sranhh.sra.co.jp>
m-ka...@sra.co.jp (Motoyuki Kasahara) writes:
> 笠原です。こんにちは。
> ようするに、これは DeleGate に限った話ではないわけですね。

はい。一般的に配布する立場と利用する立場で、どんなプログラム
はバイナリ配布のものがいいか、どんなプログラムはソース配布が
いいか、そういう判断を個人個人でやる時に、どんな点を考慮しな
いかを例をあげながら議論しているつもりです。

> ただ、現状では Sendmail, Apache, BIND といった、外部からの攻撃
> にも耐えなければならないような用途のソフトウェアも含めて、
> FreeBSD や Linux の distribution の多くでバイナリが配布すること
> が一般的になっているのはご存じかと思います。

はい。

> この現状を踏まえた上で、やっぱりそれでもバイナリの配布は止めた
> ほうが良いかどうかというのは、興味深い議論ではあるとは思うので
> すが、ちょっと話が広がり過ぎるように思います。

全部ソース配布にした方がよいとは主張していません。利用頻度と
か、更新の頻度とか、インストールのしやすさなどからして、選択
するのがよいかと思います。まず、インターネットに対してサービ
スを提供しないようなものは、バイナリでいいかと思います。ls
とか tcsh とか kterm とか。

次にインターネットに対してサービスを提供するのは、なるべくな
らソース配布を利用したいです。とはいっても、inetd, telnetd,
ftp は、バイナリです。sendmail, bind は、http://www.isc.org/
を見て、問題なさそうならバイナリを使います。このあたり数多い
から。SSH, INN, Apatch, DeleGate は、常にソースです。

ついでに宣伝しておくと、バイナリ配布のプログラムを安全に使う
ための研究もしています。次の論文を見てください。

榮樂, 新城, 板野: "位置情報を利用したシステム・コール・レベ
ルのアクセス制御", 情報処理学会研究会報告2000-OS-84-29,
Vol.2000, No.84, pp.213-220 (2000年5月)

この論文では、ガードというカーネル内のモジュールを使って付加
的にアクセス制御の機能を強化する方法について書いてあります。
特に Unix では、ファイルの内容は rwxrwxrwx のモードがあるの
に、ネットワークになると急に uid==0 か否かくらいしか効かなく
なります。ガードを使えば、この辺りを補強できます。さらに、万
一、インターネットからの攻撃で落ちて root の権限を取られたと
しても、ガードがあればそこから粘り腰を発揮して、システムを壊
滅的な破壊から保護することができます。root といっても、遠隔
から制御されているようなものは、権限を弱くすることができます。

論文は5月の時点での話で、まだ動いていないことになっています
が、今はだいぶ動いています。

この手の機能は、本当は、Windows とか MacOS とか、実質的にバ
イナリ配布しか使えないような OS で効くんだけど。Netscape は
Unix のバイナリを使ってますけど、これにガードを仕掛けたいん
です。勝手にメールを出さないようにとか、勝手に変なファイルを
アクセスしないようにとか。トロイの木馬だったらと思うと、怖く
てしょうがないわけです。HTTP の中身は、上の論文のガードでは
難しいんだけど。

> で、DeleGate に限った話じゃなく一般的な話かと思えば、ここから
> は DeleGate 固有の話なんですよね。必要とあれば一般論を挟むこと
> は構いませんが、どうもこれまで DeleGate 固有の話と一般論が噛み
> 合っていないような気がします。

DeleGate は、バイナリ配布はやめてソースがいいということで、
意見は一致したわけで、別に対立点じゃないですよね。
sendmail もバイナリでも同意見ということで。

Linux 系の Apache のバイナリの配布とデフォルトの起動は、やめ
てもらった方が世のため人のためだと思うんだけどなあ。特に一般
ユーザ用は。(どうしてもバイナリ配布ということなら、上の論文
のシステムを使ってください、と言いたい所なんですが、まあもう
少しお待ち下さい。)

> これまでだと他には、randstack (*1) や StackGuard (*2) の話とか、
> 「セキュリティというものは...」と切り出してきたとき (*1) とか。
> それぞれは価値ある情報を含んでいたりもしますが、議論に対しては
> すこし混乱を招くものであったと思います。もちろん、これは新城さ
> んの狙いではないと思いますけれど。

私はいつもネットワーク・ニュースなので、情報量が多い記事、
DeleGate を使っていない人にも役に立ちそうな記事を書きたいと
心掛けています。

> # ところで、更新されていると言っても、6.1.20 が出てから一月経ち
> # ますよね。以前はそれこそ毎日バージョンが上がってた気がするん
> # ですけど。:-D

11月28日に 6.1.21 が出ました。修正の細かい所は、メーリング・
リストで diff で出ます。

> > FreeBSD のバイナリで、DeleGate の管理者はどうなっているでしょ
> > うか? それに関するドキュメントは、どこにありますか?
> あえて直接は書きませんが、
> http://www.freebsd.org/ports/net.html
> http://www.jp.freebsd.org/www.freebsd.org/ports/net.html
> http://www.jp.freebsd.org/www.freebsd.org/ja/ports/net.html

ports は、ソースを ftp で引っ張ってきて make かけるんですよ
ね。バイナリ配布というよりは、ソース配布に近いと思います。ソー
ス配布の利点と、バイナリ配布の気軽さをうまく融合させたすばら
しい方法だと思います。

FreeBSD で検索にかかった delegate6.1.19 の ports (ちょっと古
いな)を試したのですが、ftp でこけてしまいます。壁の内側なの
で、passive で ftp しないとうまくいかないからかもしれません。

fetch: ftp.delegate.org: Not logged in
fetch: pub/DeleGate/delegate6.1.19.tar.gz: cannot get remote modification time
fetch: ftp://ftp.etl.go.jp/pub/DeleGate/delegate6.1.19.tar.gz: FTP error:

ports でどういう風に DeleGate の管理者のメール・アドレスを設
定しているかというのは、バイナリ配布と同じ問題をかかえるので
しょう。(ちなみに、DeleGate は、FreeBSD 以外のどんなホスト
でもソースを展開して make 一発でいくように作られています。)

Yasushi Shinjo

unread,
Nov 29, 2000, 3:00:00 AM11/29/00
to
新城@筑波大学情報です。こんにちは。

In article <902hbh$1nfd$1...@sranhh.sra.co.jp>


m-ka...@sra.co.jp (Motoyuki Kasahara) writes:
> 笠原です。こんにちは。

> 見つかったバグの対処を迅速にするだけが、安全性ではないですよね。
> 未来に対するバグの配慮も安全性の一環でしょう。

はい。(過去のバグを潰さないで居直っている会社もありますけど。)

> 未来のバグとなりうる、コーディングの危険性が FreeBSD SA という
> 形で指摘されていますし、開発者もこのことは認識しているようです。
> なのに、「これまでに指摘されたバグは潰しているから安全です」と
> いう過去にだけ言及しているのでは、配慮が十分とは思えません。

未来が100%大丈夫とは言っていません。ソフトウェアの安全性
は、まず、最低限は、セキュリティ・ホールになるような既知のバ
グを迅速に潰すということです。DeleGate は、これに十分合格し
ています。(CERT の応答が速い所は、合格。)次は未来のバグです
が、DeleGate はスタックのランダム化で時間かせぎできるように
なっています。時間かせぎができれば、1個所クラックされた時後
にバグを修正して残りの所が同じ手口でやられるのを防げます。こ
の点でも DeleGate は、合格です。あと、作った人が信用できるか
ですが、これも合格です。

FreeBSD SA の指摘は、3ヶ月も前に潰されたバグやコードの表面
的な見掛けだけ判断したものです。私は、FreeBSD SA の信頼性と
DeleGate の信頼性は、DeleGate の方が上だと思います。

> で、ちゃんとチェックしている外からの攻撃に晒される部分って、具
> 体的に何処なんでしょう。

DeleGate が TCP/IP から read() する所です。

> # 私が最初の記事 <8ui6ss$18t1$1...@sranhh.sra.co.jp> で引用したのは、
> # httpd.c なんですが、このファイルに書いてある関数は、外からの危
> # 険に晒される部分ではないんでしょうか。httpd.c と言う名前からし
> # て外気に晒される所かと思って選んだのですが。

このソースなら、service_http2() のこの辺りです。

if( fgetsRequest(Conn,REQ,sizeof(REQ),fc,0) == NULL || REQ[0] == 0 ){

sizeof(REQ) でバッファ・サイズを渡していて、これよりたくさん
は読みません。ここでバッファ・オーバーフローは起きません。大
きなプログラムでも、まともなプログラムなら、外部にさらされる
所は、そんなにたくさんは出てきません。

sprintf() は、長さがどうなるかは静的に予想ができます。%d な
ら 10 桁。%s なら、format の文字列と、後の文字列の長さの合計。
注意深く書けば平気です。並の人にはできません。

> > というわけで、StackGuard で DeleGate をコンパイルして使うと
> > いうのも、スタックを実行禁止にする事の次によい方法です。
> StackGuard のオーバーフロー検出機能は、やるべきチェックをやって
> ないソフトウェアを救うためのものじゃなくて、あくまでチェックをやっ
> た上で補助的に使うものですよね。

私は、人間技でやるよりも、機械でできるなら機械でやった方がい
いと思います。さらに、実行時でなくて、コンパイル時でできるな
らコンパイル時。人間の単純作業を機械に任せていこうというのが、
コンピュータ・サイエンスの目標です。たとえば、C でなくて
Java で書けば、スタック・オーバーフローの問題は100%解決
ですが、Java も大事なコンピュータ・サイエンスの成果です。
StackGuard も。

> つまり、StackGuard のようなものがあろうとなかろうと、DeleGate が
> やるべきチェックをやっているかどうかは、遥かに問題です。

私も DeleGate のコーディング・スタイルは、良くないというのは
同意です。直した方がいいのは、その通りです。でも、DeleGate
の安全性は、上で書いた意味では十分合格だと判断しています。

> 「StackGuard が使うのが良い方法」と簡単に言い切るのは、その議論
> が済んだ後じゃないですか? (私との議論の主題のほうを先にしろ、と
> いうわけじゃなくて)

私も DeleGate のコーディング・スタイル(スタック・オーバーフ
ローに弱そうに見える)は、良くないというのは、私も認めてます
し、そのあたりの議論は終わっているんじゃないですか。残った論
点は、悪いコーディング・スタイルのソフトウェアは、使うのはど
うか、具体的に DeleGate を使うのはどうか、DeleGate は本当に
強いのか弱いのか、でしょうか。

27-Nov-2000 に Red Hat ぼこぼこバグ・フィックス出てるなあ。
bind, apache, pine, netscape, bash ...

Yoshiki Kataoka

unread,
Dec 3, 2000, 3:00:00 AM12/3/00
to

片岡です。


> > 配列に対する不必要なレンジチェックを言語処理系が
> > 自動回避できる場合は少なすぎると言おうとしただけです。
>
> 人為ミスが有り得るという状態と無いという状態には大きな隔たりがあると思
> います.

ヒューマンエラーにも、凡ミス、設計のまずさ、
など色々ありますよね。

言語側でのレンジチェックには、
これらのうちの凡ミスを防ぐ意味はありそうですが、
設計に対してはむしろマイナスになりうると思います。

パスワードを検査中にレンジチェック例外が起きたとして、
それをどうするかも当然考えなければなりませんが、
ただ「subscript out of range」と *コンソールに* 表示して
止まってしまうだけでは作者以外の誰も納得しないでしょう。
きちんとした対応ができるようにするためには、
何言語であろうと例外ハンドラを書く必要があるし、
その例外ハンドラの実行条件と要件もはっきりさせなければ
なりません。

「言語がチェックしてくれるから」と安心してしまうのは
ここを忘れることにつながりませんか?
アクセス違反 *だけ* は回避できても、
システムダウンやセキュリティ・ホールが回避できなければ
結局「同じこと」である場面がほとんどでしょう。

そのとき、自動チェックのコストは何に払っているのでしょうか。

> 話変わって効率. バッファサイズが 2^n であるという情報が静的に得られる
> ならば cyclic バッファインデックスの更新は単なる論理積になりますよね.
> つまり idx の値域が 0 以上 N (= 2^n) 未満ならば
>
> if (N <= ++idx)
> idx = 0;
>
> は
>
> idx = (++idx) & N-1;
>
> となりますし, range check も
>
> if (idx & ~(N-1))
> ...;
>
> となりますが (バッファサイズを 2^n として #define する場合が多いのはこ
> れを狙っているからだと思います),

unsigned char idx;

ですね。 正直、私も使っています。

# Cの規格では整数のオーバーフローに対する動作が
# なんと「未定義」! 処理系定義ならともかく、そんな殺生な...

> C で 汎用的に書いてしまうと (open な
> どの引数でバッファサイズを与えるようにすると) これも不可能になります.

ついつい書いてしまうオーバースペックの典型ですね。
決めうちできるところを、そうすることによって
効率を稼ぐことに協力的な言語って、私は好きなんですが
人それぞれで...

> 欲しいですよね, template :-)

リンカをどうするかという問題に一抹の不安を覚えますが、
あればありがたかったです。

> > > # そういう言語と同じことをしようとすると効率ガタ落ちなのがはっきりわか
> > > # る例ですね.
> >
> > すみません、「そういう言語」という部分がわかりません。
>
> 私の頭の中には具体的には C++, 抽象的には検証論的な書き方の出来る言語が
> あります (後者は前者を使ってある程度構築可能かも知れない).
>
> C++ について実は実装に明るくないのですけど, jmp_buf を添字更新の度にス
> タックに積むようなことにはならないのではないでしょうか (少なくともそれ
> を避けるコーディングは可能なのでは).

こういうことですか?

void CharKaku(char *p, ptrdiff_t i, char a, ptrdiff_t max) throw(int)
{
if( i < 0 || max <= i ) throw 1;


*(p + i) = a;
}

> setjmp/longjmp は今の仕事でも使っています.
>
> # goto もそれなりに使います :-)

ありゃ、それは失礼しました。


Yoshiki Kataoka

unread,
Dec 3, 2000, 3:00:00 AM12/3/00
to

片岡@まぐろ状態です。


わがまま言ってすみませんでした。
じっくり拝読させて頂きました。
ありがとうございます。

> void foo(char a[], int b, int c)
> {
> int i;
> for (i = b; i < c; i++) {
> a[i] = 0;
> }
> }
>
> で、配列のrange checkをするPascal, Ada, Javaのような言語では、コンパイ
> ラがrange checkを特別扱いするので、チェックをループの外に追い出すこと
> ができます。(Javaの場合、上では 0 <= b と c <= a.length をチェックすれ
> ば良い。) また、上のコンパイル時に呼び出し元もわかっているようなときに
> は、range checkをコンパイル時にすべて済ませてしまえる場合もあるでしょ
> う。

なるほど。 Cではこうなってしまいますね。

void foo_caller1(void)
{
char array[256];
int begin, end;

begin = func1();
end = func2();

if(0 <= begin && end <= 256)
{
foo(a, begin, end);
}
}

void foo(char a[], int b, int c)
{
int i;

assert(0 <= b && c <= 256);


for (i = b; i < c; i++) {
a[i] = 0;
}
}

foo の中に 256 と書かされるあたり、ものすごくイヤです。
(array_t のような構造体にすれば別でしょうけど)

ところで、何がイヤなのでしょうか。 根本的な問題として。
私思うに、問題は foo の設計にあり、言語の善し悪しとは
関係がなさそうに見えるのです。

foo_caller1 の中の if のようなチェックが書けないようであれば
そのプログラマには適性がないと言わざるを得ません。


> void foo(array_t *a, int b, int c)
> {
> int i;
> for (i = b; i < c; i++) {
> CharKaku(a->body, i, 0, a->length, error);
> }
> }
> と書いたとします。
>
> induction variableや不等式に関する超強力な推論機能をもつCのコンパイラ
> がたとえ仮にあったとしても、CharKakuのチェック
> if( i < 0 || max <= i ) longjmp(jb, 1);
> をループの前に追い出して、
> if (b < 0) longjmp(error, 1);
> if (a->length <= c - 1) longjmp(error, 1);
> とすることはできません。

なるほど。
手動でチェックするからインライン化しても最適化できないのですね。

# うげー

void foo_caller1(jmp_buf jb1)
{
array_t a;
int begin, end;
jmp_buf jb2;
volatile int e;

a.body = (char *)malloc(sizeof(char) * (a.length = 256));
if((e = setjmp(jb2)) == 0)
{
begin = func1();
end = func2();

if(0 <= begin && end <= a.length)
{
int i;
assert(0 <= begin && end <= a.length);
for (i = begin; i < end; i++) {
if( i < 0 || a.length <= i ) longjmp(jb2, 1);
a.body[i] = 0;
}
}
}
else
{
free(a.body);
longjmp(jb1, e);
}

free(a.body);
}

そもそも、こんな手動チェックは書きませんが。

私が CharKaku を持ち出したのは、
Cでコードを書いているときに「他の言語では」と
しきりに言う人たちのレンジチェックに対する思想が
上のようなコードにつながりかねないと言いたかったからです。


> 常にチェックするCharKakuに加えて、「ループ用に上下限だけチェックするマ
> クロ」とかを用意し、ループ本体ではチェックなしの配列アクセスをするよう
> にすれば、Javaなどと同等の効率が得られますが、これは(間違いの危険が増す
> ことを別としても)CharKakuと「等価」とはとても呼べないと思います。

「等価」は引っ込めたはずなのですが、
以上のように設計思想として「同じこと」でないことに
まだ納得がいっていません。


Motoyuki Kasahara

unread,
Dec 4, 2000, 3:00:00 AM12/4/00
to
笠原です。こんにちは。

> 未来が100%大丈夫とは言っていません。ソフトウェアの安全性
> は、まず、最低限は、セキュリティ・ホールになるような既知のバ
> グを迅速に潰すということです。DeleGate は、これに十分合格し
> ています。

私も「DeleGate は、未来も100%大丈夫ではない」と言っているわ
けではありません。新城さんの表現に倣うなら、未来という点では合格
に達していないと言いたいのです。


> あと、作った人が信用できるかですが、これも合格です。

新城さんの心の内では合格でも、他の人を納得させられるような根拠は
残念ながらありません。

作者が信用できるかどうかは、作品の成り立ちや、開発方針、メーリン
グリストでの発言などから各ユーザが判断しなければならないと思うの
ですが、減点が大きくて合格点には達していない、というのが私の印象
です。

# 作者が意図的に侵入手口を作るような真似はしない、といったレベル
# では無論信用できるでしょうが、いくらなんでも論外なので除外しま
# す。作者に対する信用とは別に、作品の開発自体に対する信頼性、安
# 心感という評価項目にしても良いです。

少し前に、内田さんが同様の感想を述べられていましたが、私にも
DeleGate には安全性を語る上で不安材料がいくつかあります。

* コーディングの手抜き
これまでさんざん言っていることです。大丈夫かどうかはあえて
置いておくとしても、なぜこのようなスタイルを採用してそのま
まにしておくんでしょうか。品質を下げていることも事実です。

* 解析しづらいログ
なるべく安全性を維持しつつ日々の運用をこなすつもりなら、こ
れはかなり不安では。

* 不必要に数多くのプロトコルへの対応
とても全部は使いきれないほど多数のプロトコルに対応して、し
かも 1 個のバイナリになっています。必要な機能だけに絞って
コンパクトになっていたほうが、安全性の面では有利でしょう。

* いたずらに難解な設定方法
数多くのプロトコルに対応していることによって設定パラメタが
多岐に渡っていることに加えて、設定ファイルじゃなくてコマン
ド行オプションでの指定がメインですから、文法が必要以上に難
解になってしまっています。

いくら、マニュアルをちゃんと読むのがユーザの責任で、無保証
だから運用で起きたことは作者に責任はないと言っても、これで
は管理者の意図通りに正しく設定するのをわざわざ難しくしてい
るようなものです。

たしかにどれも直接的に危険には繋がりません。しかし、防火壁の外側
からの攻撃にも耐えなくてはいけないソフトウェアが、これだけ欠点を
抱えた設計をしてしまっているという点で、信用性 (安心感といっても
良いです) ではマイナス点が多すぎます。

それに、これらの不安材料に対する指摘は、過去に delegate メーリン
グリストやその他の場所でなされたことと思います。しかし、その度に
作者氏は「それよりも優先したい事がある (つまり優先度は低い)」と
いう発言をされてきたのではなかったでしょうか。

こうした不安材料を放置したまま、逆に優先されてきたのが多数の機能
追加なわけですから、安全性に対する姿勢に対しても、高い評価は付け
られません。


> FreeBSD SA の指摘は、3ヶ月も前に潰されたバグやコードの表面
> 的な見掛けだけ判断したものです。私は、FreeBSD SA の信頼性と
> DeleGate の信頼性は、DeleGate の方が上だと思います。

私も、3ヶ月も前に潰されたバグやコードに関する SA の指摘はまっ
たく的外れだと思います。

私が「FreeBSD SA の指摘」といっているのは、"with potentially
dozens of different exploitable buffer overflows" という部分のこ
とです。新城さんもその点は「はい。そうです」と認めましたよね。


> このソースなら、service_http2() のこの辺りです。
>
> if( fgetsRequest(Conn,REQ,sizeof(REQ),fc,0) == NULL || REQ[0] == 0 ){
>
> sizeof(REQ) でバッファ・サイズを渡していて、これよりたくさん
> は読みません。ここでバッファ・オーバーフローは起きません。大
> きなプログラムでも、まともなプログラムなら、外部にさらされる
> 所は、そんなにたくさんは出てきません。
>
> sprintf() は、長さがどうなるかは静的に予想ができます。%d な
> ら 10 桁。%s なら、format の文字列と、後の文字列の長さの合計。
> 注意深く書けば平気です。並の人にはできません。

後半の sprintf() の話は DeleGate の話じゃなくて、一般論でしょう。
sprintf() で文字列領域を上書きする際に、DeleGate でチェックして
いるかどうかは別です。で、この点がとっても怪しいと思っているわけ
です。

前半の話はようするに、「gets() じゃなくて、ちゃんと fgets() 使っ
てます」くらいの意味ですね。「DeleGate が TCP/IP か ら read() す
る所は安全」と言っても、読み込んだ内容に基づいて処理を行う部分は
それとは別ですし、そっちの安全性も重要です。
________________________________________________________________
笠原 基之(かさはら もとゆき)

Kazuo Fox Dohzono

unread,
Dec 4, 2000, 3:00:00 AM12/4/00
to
堂園です.

In article <90djdk$cc$1...@news01ch.so-net.ne.jp>
"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> writes:

> パスワードを検査中にレンジチェック例外が起きたとして、
> それをどうするかも当然考えなければなりませんが、
> ただ「subscript out of range」と *コンソールに* 表示して
> 止まってしまうだけでは作者以外の誰も納得しないでしょう。

仕様や状況によってはそれでも ok だと思います.

> 「言語がチェックしてくれるから」と安心してしまうのは
> ここを忘れることにつながりませんか?

言語仕様によっては「ハンドラが設定されてないけどいいの?」という警告を
出させることも可能でしょう. または, 「ここはチェックしなくとも良い」こ
とを予め表記しなければならないようにするとか.

> unsigned char idx;
>
> ですね。 正直、私も使っています。

unsigned char のバイト数が 1 だったり 2 だったりするので流石にそこまで
は私もやりません.

> > C で 汎用的に書いてしまうと (open な
> > どの引数でバッファサイズを与えるようにすると) これも不可能になります.
>
> ついつい書いてしまうオーバースペックの典型ですね。
> 決めうちできるところを、そうすることによって
> 効率を稼ぐことに協力的な言語って、私は好きなんですが
> 人それぞれで...

そういう具合いに書けて, かつ, 効率を落さない処理系があってもいいと思い
ます.

> こういうことですか?
>
> void CharKaku(char *p, ptrdiff_t i, char a, ptrdiff_t max) throw(int)
> {
> if( i < 0 || max <= i ) throw 1;


> *(p + i) = a;
> }

こういう具合いにしか書けない言語なら, こう書くしかないでしょう. いつで
もチェック無しのコードを書けてしまう時点で駄目なんじゃないかと.

Motoyuki Kasahara

unread,
Dec 4, 2000, 3:00:00 AM12/4/00
to
笠原です。

> > この現状を踏まえた上で、やっぱりそれでもバイナリの配布は止めた
> > ほうが良いかどうかというのは、興味深い議論ではあるとは思うので
> > すが、ちょっと話が広がり過ぎるように思います。
>
> 全部ソース配布にした方がよいとは主張していません。利用頻度と
> か、更新の頻度とか、インストールのしやすさなどからして、選択
> するのがよいかと思います。

私も全部ソースにしたほうが良いいう主張をするつもりはありまんし、
新城さんがそう主張しているとも思ってません。「外部からの攻撃に
も耐えなければならないような用途のソフトウェアも含めて」と書い
たのは、そういう含みがあってのことです。

| ただ、現状では Sendmail, Apache, BIND といった、外部からの攻撃
| にも耐えなければならないような用途のソフトウェアも含めて、
| FreeBSD や Linux の distribution の多くでバイナリが配布すること
| が一般的になっているのはご存じかと思います。

> DeleGate は、バイナリ配布はやめてソースがいいということで、
> 意見は一致したわけで、別に対立点じゃないですよね。
> sendmail もバイナリでも同意見ということで。

あのー、もしもし?
話が広がりすぎるから、私はバイナリの配布の是非に関する議論はや
りたくないと言っただけです。同意見だなどは一言も言ってません。

記事に情報を詰め込むことを心掛けるのはご立派ですが、そっちにば
かり夢中になって、それ以外の点がまったく緩みきった記事になって
ません?

話が散漫で焦点がまったくぼやけてしまっているわ、人の記事をよく
読まずにフォローするわ、おまけについ調子に乗ってしまったのか
「#define を使っていても、スタック・オーバーフローは起きるもの
は起きる」なんて書いちゃうわ。

あーあ。
________________________________________________________________
笠原 基之(かさはら もとゆき)

KATAYAMA Yoshio

unread,
Dec 11, 2000, 5:14:58 AM12/11/00
to
In article <90djdk$cc$1...@news01ch.so-net.ne.jp>,
"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> writes:

># Cの規格では整数のオーバーフローに対する動作が
># なんと「未定義」! 処理系定義ならともかく、そんな殺生な...

処理系定義では、「オーバーフローでシグナルを発生させる」ことがで
きなくなります。
--
片山@PFU

Yoshiki Kataoka

unread,
Dec 11, 2000, 8:36:12 PM12/11/00
to
片岡です。

>仕様や状況によってはそれでも ok だと思います.


ひょっとして、某有名ブランドのことですか?

# だとすると comp な話題ではなくなりそう


>言語仕様によっては「ハンドラが設定されてないけどいいの?」という警告を
>出させることも可能でしょう. または, 「ここはチェックしなくとも良い」こ
>とを予め表記しなければならないようにするとか.

ハンドラの記述を義務づけるなら、Cと同じでしょう。

>unsigned char のバイト数が 1 だったり 2 だったりするので流石にそこまで
>は私もやりません.


そうですか、それは残念。


typedef unsigned char uint8;


>そういう具合いに書けて, かつ, 効率を落さない処理系があってもいいと思い
>ます.


うーん。 Cは違うんですかね。


>こういう具合いにしか書けない言語なら, こう書くしかないでしょう. いつで
>もチェック無しのコードを書けてしまう時点で駄目なんじゃないかと.


何の話でしたっけ??

確か C++ 例外処理の *実装* だったような...


Takao Ono

unread,
Dec 11, 2000, 10:26:17 PM12/11/00
to
小野@名古屋大学 です.

ちゃちゃ... だろうなぁ, やっぱり.

<90fvv0$2gqh$1...@news2.rim.or.jp>の記事において
doh...@hf.rim.or.jpさんは書きました。
dohzono> > unsigned char idx;
dohzono> > ですね。 正直、私も使っています。
dohzono> unsigned char のバイト数が 1 だったり 2 だったりするので流石にそこまで
dohzono> は私もやりません.
ん~, C の言語仕様では unsigned char は 1バイトじゃありませんでしたっ
け? 何ビットかは処理系依存 (CHAR_BIT で参照可能) ですけど.
--
名古屋大学 工学部 電子工学科 平田研究室
小野 孝男

Kazuo Fox Dohzono

unread,
Dec 12, 2000, 12:03:47 PM12/12/00
to
堂園です.

> >仕様や状況によってはそれでも ok だと思います.
>
> ひょっとして、某有名ブランドのことですか?

私は実際に仕事で「何かおかしなことを検出したら停止するように作ってくれ」
という仕様 (要請) に基づいてプログラムを書いたことがあります.

> >言語仕様によっては「ハンドラが設定されてないけどいいの?」という警告を
> >出させることも可能でしょう. または, 「ここはチェックしなくとも良い」こ
> >とを予め表記しなければならないようにするとか.
>
> ハンドラの記述を義務づけるなら、Cと同じでしょう。

そうかなあ.

> >unsigned char のバイト数が 1 だったり 2 だったりするので流石にそこまで
> >は私もやりません.

これは「8 ビットだったり 16 ビットだったりする」としておきます.

# Message-ID: <9145sp$bvr$1...@henry.hirata.nuee.nagoya-u.ac.jp>

> typedef unsigned char uint8;

これでも 16 ビットになる環境があります.

> >こういう具合いにしか書けない言語なら, こう書くしかないでしょう. いつで
> >もチェック無しのコードを書けてしまう時点で駄目なんじゃないかと.
>
> ?
> 何の話でしたっけ??
>
> 確か C++ 例外処理の *実装* だったような...

C++ または検証論的に書ける言語. プログラマ (人間) が何かのチェックをサ
ボってしまわないように (チェックが簡単なように) 工夫したとしても, そう
でないように簡単に書けてしまう環境下では意味がないのかも, という話.

そんなに私の話ってわかりにくいですか?

--
Kazuo Fox Dohzono / doh...@hf.rim.or.jp

[12],(6,9),0,0,2
(4/1449/3742)

Shiozaki Takuya

unread,
Dec 13, 2000, 11:31:59 PM12/13/00
to

塩崎です。


<914012$2mb$1...@news01cf.so-net.ne.jp>の記事において
kat...@ka2.so-net.ne.jpさんは書きました。

>> >unsigned char のバイト数が 1 だったり 2 だったりするので流石にそこまで
>> >は私もやりません.
>> そうですか、それは残念。
>> typedef unsigned char uint8;

最近の処理系(ISO C:1999 準拠)なら、stdint.h を include すれば
uint8_t が使えますね。

# ただし、255 + 1 が 0 とは限らない気がする。


では。
--
Takuya SHIOZAKI / ASTEC Products, Inc.

KATAYAMA Yoshio

unread,
Dec 14, 2000, 3:35:11 AM12/14/00
to
片山@PFUです。

In article <919ifv$9h0$1...@tokyonet-entrance.astec.co.jp>,
tshi...@astec.co.jp (Shiozaki Takuya) writes:

>最近の処理系(ISO C:1999 準拠)なら、stdint.h を include すれば
>uint8_t が使えますね。

使えるとは限らないようです。

7.18.1.1 Exact-width integer types
...
3 These types are optional. However, if an implementation
provides integer type with widths of 8, 16, 32, or 64 bits,
it shall define the corresponding typedef names.

># ただし、255 + 1 が 0 とは限らない気がする。

uint8_t が使える処理系なら、(uint8_t)(255 + 1) が 0 になることが
保証されます。
--
片山@PFU

Tomoaki NISHIYAMA

unread,
Dec 14, 2000, 4:24:20 AM12/14/00
to
ka...@pfu.co.jp (KATAYAMA Yoshio) writes:

> 片山@PFUです。
...


> uint8_t が使える処理系なら、(uint8_t)(255 + 1) が 0 になることが
> 保証されます。

整数のoverflowはトラップされないことに決まったということですか?
--
Tomoaki Nishiyama
e-mail:tom...@nibb.ac.jp
National Institute for Basic Biology

KATAYAMA Yoshio

unread,
Dec 14, 2000, 10:53:09 PM12/14/00
to
In article <86bsuf5...@koke.nibb.ac.jp>,
Tomoaki NISHIYAMA <tom...@nibb.ac.jp> writes:

>> uint8_t が使える処理系なら、(uint8_t)(255 + 1) が 0 になることが
>> 保証されます。

>整数のoverflowはトラップされないことに決まったということですか?

符号無し整数の演算や整数から符号無し整数への変換ではオーバーフロー
は起きません。(cf. 6.2.5, 6.3.1.3)
--
片山@PFU

Yoshiki Kataoka

unread,
Dec 17, 2000, 11:52:47 AM12/17/00
to
片岡です。


>私は実際に仕事で「何かおかしなことを検出したら停止するように作ってくれ」
>という仕様 (要請) に基づいてプログラムを書いたことがあります.


「異常に気づいたら極力短時間でその旨を親へ通知せよ」ですね。
確かにそういうのは良くあることです。

ここで注意すべきことは、エラーを検出できるモジュールと、
エラーに対する最善の処置に責任を持つモジュールが、
よく構造化されたプログラムほど別モジュールである場合が多い
ことです。

どのように「停止」するのか、について特殊な仮定を(しばしば沢山)
しなければならないのが、エラー処理を言語任せにすることや、
汎用モジュールの中で安直に exit することです。

この反対で、どのように「停止」するのかを決め打ちせずにおけるのが、
諸言語の「例外サポート」やCの <setjmp.h> でしょう。

それで、

>> ハンドラの記述を義務づけるなら、Cと同じでしょう。
>
>そうかなあ.

この話、配列のレンジチェックが元ネタでしたよね。

>> typedef unsigned char uint8;
>
>これでも 16 ビットになる環境があります.

他の方に書かれてしまいましたが、
「整数の長さに責任を持つ」役割のモジュールを
用意するという意味です。(この場合、ヘッダか)


>C++ または検証論的に書ける言語. プログラマ (人間) が何かのチェックをサ
>ボってしまわないように (チェックが簡単なように) 工夫したとしても, そう
>でないように簡単に書けてしまう環境下では意味がないのかも, という話.
>
>そんなに私の話ってわかりにくいですか?

この段落のみ。

普段、あまり使わない言い回しをされたせいかも知れません。

要するに、チェック(アルゴリズム)の最適化がプログラマの責任範囲に
あることが意味がない(?)ということでしょうか。 前にも書きましたが、
適切なチェックが書けることや、デバイスの極性を *間違えないように
気をつける能力* などは、プロになる人には必須だと思うのです。
たとえ道具がどんなに進歩しても、結局その先にまた間違えては
ならないことが出てきます。分業はあってよいでしょう。しかし、
それぞれの持ち場で間違えないことは必要です。

Yoshiki Kataoka

unread,
Dec 15, 2000, 10:16:10 PM12/15/00
to
片岡です。


>># Cの規格では整数のオーバーフローに対する動作が
>># なんと「未定義」! 処理系定義ならともかく、そんな殺生な...
>
>処理系定義では、「オーバーフローでシグナルを発生させる」ことがで
>きなくなります。


なぜですか?
よろしければ、もう少し詳しく拝聴できれば幸いです。
(特に、未定義の場合と、処理系定義の場合の違いについて)


Kazuo Fox Dohzono

unread,
Dec 17, 2000, 10:11:20 PM12/17/00
to
堂園です.

In article <91ir64$hca$2...@news01bd.so-net.ne.jp>
"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> writes:

> >私は実際に仕事で「何かおかしなことを検出したら停止するように作ってくれ」
> >という仕様 (要請) に基づいてプログラムを書いたことがあります.
>
> 「異常に気づいたら極力短時間でその旨を親へ通知せよ」ですね。

余計なバスアクセスも許されなかったので di して halt するようにしました.

# 半年以上 24h 稼働していて出荷時のハードウェアテスト以外で停止したと
# いう話はまだありませんけど.

> 要するに、チェック(アルゴリズム)の最適化がプログラマの責任範囲に
> あることが意味がない(?)ということでしょうか。 

いえ, 結果的にチェックするコードが (半) 自動的に生成可能な言語とそうで
ない言語とは同列に扱えないのではないかということです.

> 前にも書きましたが、適切なチェックが書けることや、デバイスの極性を *
> 間違えないように気をつける能力* などは、プロになる人には必須だと思う

> のです。たとえ道具がどんなに進歩しても、結局その先にまた間違えてはな


> らないことが出てきます。分業はあってよいでしょう。しかし、それぞれの
> 持ち場で間違えないことは必要です。

でも, 人間のすることですからねえ.

KATAYAMA Yoshio

unread,
Dec 18, 2000, 12:11:37 AM12/18/00
to
片山@PFUです。

In article <91ir63$hca$1...@news01bd.so-net.ne.jp>,
"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> writes:

処理系定義は、

3.10 implementation-defined behavior: Behavior, for a
correct program construct and correct data, that depends on
the characteristics of the implementation and that each
implementaion shall document.

と規定されています。つまり、「正しいプログラムの動作」についての
規定です。

「オーバーフローでシグナルを発生させる」のは、プログラムがエラー
を起こしていることを通知しようとしているわけで、その動作は処理系
定義では規定できません。

もし、オーバーフローの動作を処理系定義とするならば、そのときの算
法(arithmetic)を各処理系が規定しなければなりません。即ち、どの
ような演算結果が得られるかが規定されるわけで、シグナルを発生させ
る(=演算結果が得られない)ことができなくなります。
--
片山@PFU

Yoshiki Kataoka

unread,
Dec 18, 2000, 7:13:21 AM12/18/00
to
片岡です。


>余計なバスアクセスも許されなかったので di して halt するようにしました.


おお、なるほど。 仕方ないですね。
exit だの言語任せだのでは仮定しきれない要件の秀逸な例ですね。


>> 要するに、チェック(アルゴリズム)の最適化がプログラマの責任範囲に
>> あることが意味がない(?)ということでしょうか。 
>
>いえ, 結果的にチェックするコードが (半) 自動的に生成可能な言語とそうで
>ない言語とは同列に扱えないのではないかということです.


Cの場合、必須のチェックはモジュールに内蔵させることで
うっかり忘れを防ぎますよね。どの段で必須なのかをはっきり
させながら。

確かに、同列には扱えないでしょう。


>でも, 人間のすることですからねえ.


怖いですねえ。


Yoshiki Kataoka

unread,
Dec 18, 2000, 7:34:50 AM12/18/00
to
片岡です。

無理言ってすみませんでした。
ありがたく拝読させて頂きました。


>処理系定義は、
>
> 3.10 implementation-defined behavior: Behavior, for a
> correct program construct and correct data, that depends on
> the characteristics of the implementation and that each
> implementaion shall document.
>
>と規定されています。つまり、「正しいプログラムの動作」についての
>規定です。
>
>「オーバーフローでシグナルを発生させる」のは、プログラムがエラー
>を起こしていることを通知しようとしているわけで、その動作は処理系
>定義では規定できません。


つまり、

・シグナルが発生するのは「正しくないプログラム」である
・プログラムが「正しくない」ためには、結果が規定できない

ということですね。

1点目を存じませんでしたゆえ、
これから自分で調べてみようと思います。

ありがとうございました。


>もし、オーバーフローの動作を処理系定義とするならば、そのときの算
>法(arithmetic)を各処理系が規定しなければなりません。即ち、どの
>ような演算結果が得られるかが規定されるわけで、シグナルを発生させ
>る(=演算結果が得られない)ことができなくなります。


自分で調べると言っておいて何ですが、
「動作」のうち、「演算結果」を除く構成要素が
各処理系の特徴に依存していても良さそうに
思っています。


0 new messages