注意 2013 年くらいに調べた話なので 変化していることもあるかもしれません 2

Similar documents
ソケット API プロセス間通信の汎用 API プロセス : プログラムのひとつの単位 ex)./a.out とかやると 1 つのプロセスが立ち上がる ソケット API IPv4 IPv6 UNIX domain (UNIX 計算機内プロセス間通信 ) 本実験では IPv4 の TCP および UD

BSDソケットAPI リファレンスマニュアル

目次 1. DB 更新情報受信 SW 仕様書 構成および機能 全体の構成 DB 更新情報受信 SW の機能 ソフトウェアの設計仕様 DB 更新情報受信 SW の仕様 資料編... 5

演算増幅器

実験 6 通信基礎実験 1 目的 ネットワークを通じてデータ転送を行うことを体験的に学ぶために 本実験ではT CP/IPプロトコルを使い ワークステーション間で通信を行うクライアントサーバモデルのプログラムを作成する 2 解説 1 ネットワークとプロトコルネットワーク ( コンピュータネットワーク

ソフトウェア開発実践セミナー ネットワークの基礎と UNIX ネットワークプログラミング 金子勇 土村展之 情報理工学系研究科数理情報学専攻 2002 年 11 月 6 日 ( 第 4

情報ネットワーク演習 2006年10月5日

PowerPoint プレゼンテーション

ネットワーク実験

スライド 1

BSDソケットによるIPv6プログラミングを紐解く

rzab6pdf.ps

Prog1_12th

1) // 2) I/O 3) Japan Advanced Institute of Science and Technology 2013/07/26 1

2006年10月5日(木)実施

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション

(Microsoft PowerPoint - janog23-server-ipv6-rel-public.ppt [\214\335\212\267\203\202\201[\203h])

システムインテグレータのIPv6対応

Microsoft PowerPoint - 第5章補足-DB2組み込みSQL.ppt

PowerPoint プレゼンテーション

演算増幅器

オペレーティングシステムとネットワークプログラミング 担当 : 吉藤英明 yoshfuji+camp2008 AT wide.ad.jp セキュリティ & プログラミングキャンプ /08 OS プロトコルスタック (C)2008 YOSHIFUJI Hideaki,

多言語ドメイン名の実装 mdnkit 石曽根信 ( 株 ) SRA 2001/12/04 日本語ドメイン名解説 / mdnkit 1 mdnkit 多言語ドメイン名を扱うためのツールキット 正規化 エンコード変換等を提供するライブラリとコマンド 既存アプリケーシ

PowerPoint プレゼンテーション

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

【注意事項】RXファミリ 組み込み用TCP/IP M3S-T4-Tiny

テキスト処理第 12 回 ( ) 田中哲産業技術総合研究所情報技術研究部門 u.ac.jp /

2. ネットワークアプリケーションと TCP/IP 2.1. クライアント / サーバモデル TCP/IP プロトコルに従うネットワークアプリケーションの典型的モデルは, クライアント / サーバモデルである. クライアント / サーバモデルでは, クライアントからの要求に対してサーバがサービスを提

TCP UDP TCP UDP send()sendto()sendmsg() recv()recvfrom()recvmsg() OS Passive Active TCP UDP IP TCP UDP MTAMail Transf

02: 変数と標準入出力

AquesTalk Mac マニュアル

ソケットライブラリの改善 socket library improvement 田中哲 産業技術総合研究所

Microsoft PowerPoint - kougi6.ppt

通信プログラムの試作ーーー UDP を用いたじゃんけんゲームシステム ーーーー裘彬濱 南山大学情報理工学部 ソフトウェア工学科青山研究室

AquesTalk for WinCE プログラミングガイド

main main Makefile Makefile C.5 Makefile Makefile Makefile A Mech (TA ) 1. Web ( iku

プログラミングI第10回

Microsoft PowerPoint - kougi11.ppt

Boost.Preprocessor でプログラミングしましょう DigitalGhost

Microsoft Word - no15.docx

memo

v6prog-05.ppt

3 3.1 LAN ISDN (IP) 2 TCP/UDP IP IP IP IP (Ethernet) Ethernet LAN TCP/UDP LAN Ethernet LAN 2: Ethernet ATM, FDDI, LAN IP IP IP 3 IP 2 IP IP IP IP IP 3

02: 変数と標準入出力

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

AsteriskのIPv6対応について

12.1 インターネットアドレス インターネットアドレス インターネットアドレス 32 ビットの長さを持つインターネットに接続されたマシンを識別するのに使う インターネットアドレスは ピリオドで区切られたトークンの並びで表現されることもある インターネットアドレス

PowerPoint プレゼンテーション

情報科学実験ガイダンス

演算増幅器

情報ネットワーク演習 2007 年 10 月 11 日 ( 木 )

Microsoft PowerPoint pptx

PYTHON 資料 電脳梁山泊烏賊塾 PYTHON 入門 文字列 文字列リテラル プログラムの中で文字列を表す方法は幾つか有るが 基本的な方法は下記の 2 種で有る 対象と成る文字の集まりをダブルクオーテーション ( " ) で囲うか シングルクオーテーション ( ' ) で囲う PYTHON3 "

文字列 2 前回の授業ではコンピュータ内部での文字の取り扱い 文字型の変数 文字型変数への代入方法などを学習した 今回は 前回に引き続き 文字処理を学習する 内容は 標準入出力 ( キーボード ディスプレイ ) での文字処理 文字のファイル処理 文字を取り扱うライブラリ関数である 標準入出力 Lin

ユーティリティ 管理番号 内容 対象バージョン 157 管理情報バッチ登録コマンド (utliupdt) のメッセージ出力に対し リダイレクトまたはパイプを使用すると メッセージが途中までしか出 力されないことがある 267 転送集計コマンド (utllogcnt) でファイル ID とホスト名の組

memo

Microsoft Word - Cプログラミング演習(9)

Microsoft PowerPoint - CproNt02.ppt [互換モード]

計算機概論

PowerPoint プレゼンテーション

02: 変数と標準入出力

ポインタ変数

プログラミング基礎I(再)

02: 変数と標準入出力

KASAGO TCP/IP ユーザーズマニュアル 簡易版

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

SDC_SDIO_STM32F4 の説明 2013/09/17 SDIO インターフェースで SD カードをアクセスするプログラムのプロジェクトサンプルです FAT でファイルアクセスするために FatFs( 汎用 FAT ファイルシステム モジュール ) を使用しています VCP(USB 仮想 C

02: 変数と標準入出力

Microsoft Word - appendix_b_srft.doc

r4.dvi

Chapter - UDP のプログラミング - UDP ネットワークプログラミングで TCP の次に多い通信方法が UDP だと思われます UDP はデータが宛先に届いたかどうかを関知しないため データの到着を保障しない点が TCP と異なります そのため UDP を使った通信を行うプログラムを書

C言語におけるファイル入出力の高速化

netmapによる 実践パケット処理プログラミング

21 章のお話

slide4.pptx

ファイル入出力

02: 変数と標準入出力

Microsoft PowerPoint - 5Chap15.ppt

Presentation title (on one or two lines)

C言語講座 ~ファイル入出力編~

ネットワークプログラミング

Microsoft PowerPoint - kougi8.ppt

演算増幅器

ファイル入出力

: Nonblocking I/O readpartial read EOF Solaris FILE 256 ungetc SEGV errno stdio considered harmful p.

8. Windows の補足情報 コマンドの使用についての説明です Windows からのファイル直接印刷 Windows でコマンドを使用したファイル直接印刷の方法についての説明です この機能はネットワーク接続をしているときに使用できます この方法で印刷できるファイルは 本機が搭載しているエミュレ

AquesTalk2 Mac マニュアル

1.SqlCtl クラスリファレンス SqlCtl クラスのリファレンスを以下に示します メソッドの実行中にエラーが発生した場合は標準エラー出力にメッセージを出力します (1)Connect() メソッド データベースへ connect 要求を行います boolean Connect(String

Microsoft Word - no204.docx

slide5.pptx

Prog1_10th

プレポスト【解説】

J.JSSAC Vol. 7, No. 2, Mathematica Maple,., Open asir Open xxx asir. Open xxx Open asir, asir., Open xxx, Linux Open asir Open sm1 (kan/sm1). C

今ならきっともっとよく分かる, 問題追求 ( デバッグ ) の仕方

02: 変数と標準入出力

Microsoft Word - VBA基礎(6).docx

k_seminar_hands_on_for_linux_beginner.pptx

第12回 モナドパーサ

◎phpapi.indd

Transcription:

Unix domain socket API の ポータビリティ問題 田中哲産業技術総合研究所情報技術研究部門 2016-07-02 1

注意 2013 年くらいに調べた話なので 変化していることもあるかもしれません 2

趣旨 Unix domain socket をさまざまな環境でテス トした とてもとても多様な振る舞いが観測できた そもそも API が腐っている API をデザインする人はそうならないように気をつけましょう API を使う人は罠にはまらないよう気をつけま しょう 3

Unix domain socket をテストした Debian GNU/Linux x86_64 Debian GNU/Linux ARM Debian GNU/kFreeBSD Debian GNU/Hurd NetBSD FreeBSD Darwin (PureDarwin) SunOS (OpenIndiana) Haiku Minix Cygwin OpenBSD 5.1 OpenBSD 5.2 DragonFly BSD MirOS いろいろなカーネルを試すのが興味深い結果を得るポイント ( ふつうソケットはカーネルで実装されるため ) 4

Unix domain socket パス名をアドレスとして通信 アドレスは struct sockaddr_un 構造体で表現 あとは TCP/IP とだいたい同じ 5

Unix domain socket の クライアントとサーバ サーバのアドレス クライアント : クライアントのアドレス c = socket(af_unix, SOCK_STREAM, 0); connect(c, &saddr, saddrlen); サーバ : serv = socket(af_unix, SOCK_STREAM, 0); bind(s, &saddr, saddrlen); listen(s, SOMAXCONN); c = accept(serv, &caddr, &caddrlen) 6

アドレスを扱うシステムコール アプリケーションからカーネルへ struct sockaddr *addr と socklen_t len を渡す bind, connect, sendto, sendmsg カーネルからアプリケーションへ struct sockaddr *addrbuf と socklen_t *lenp を渡す *lenp は addrbuf に確保したバッファの長さカーネルは *lenp を実際の長さに書き換える accept, getsockname, getpeername, recvfrom, recvmsg 7

struct sockaddr_un Unix domain socket のアドレスはパス名 struct sockaddr_un を使う struct sockaddr_un は以下のフィールドを持つ sa_family_t sun_family Address family. (POSIX) char sun_path[] Socket pathname. (POSIX) 実際の長さは決まっていない 実装依存で他のフィールドがあるかもしれない sun_family sun_path 8

sockaddr_un のバリエーション 4.4BSD: sun_len フィールドを追加 Darwin, Hurd, Haiku も追随 Debian GNU/kFreeBSD にもある sun_family フィールドのサイズ 1: sun_len フィールドがあるOS および Minix 2: その他 sun_path のサイズ 104: 4.4BSD (NetBSD, FreeBSD, OpenBSD, DragonFly BSD, MirOS) 108: GNU/Linux, Hurd, SunOS, Cygwin 126: Haiku 127: Minix Debian GNU/kFreeBSD (squeeze): user land は 108, kernel は 104 (wheezy では両方 104) 9

ソケットアドレスの終端 パス名は可変長なので終端を示す必要がある C 言語の文字列としてのNUL 文字による終端 bind() や connect() の長さ引数による終端 sun_path フィールドのサイズによる終端 (sun_len が存在すれば その長さによる終端 ) これで混乱が起きないわけがない 10

バリエーション豊かな挙動 getsockname と getpeername でソケットの名前を調べる Minix は相対パスで bind しても getsockname などで は絶対パスが返る Hurd は getsockname, getpeername を未サポート getsockname は sun_path に "\0" という 1byte が返り getpeername は EOPNOTSUPP で失敗する OpenBSD 5.2 は短いパスで bind すると getsockname などでは \0 で残りが塗りつぶされてパスは常に 104 バイトになる 他の環境は Minix と Hurd 以外 bind に与えたパスが NUL 終端されている限り そのままの長さで返す 11

バリエーション豊かな挙動 (2) ひとつのファイルを示すパスは複数ある サーバで bind したアドレスとクライアントで connect したアドレスが違ったらどうなるか? connect した後 getpeername すると SunOS と Cygwin は connect に与えたアドレスが返る 他はサーバの bind に与えたアドレスが返る 12

バリエーション豊かな挙動 (3) ソケットを bind せずに getsockname 空の sockaddr (family もなし ): DragonFly BSD, OpenBSD, MirOS, SunOS sun_path が空になる : Linux sun_path が空になり その直後に NUL: Cygwin sun_path に 1byte の NUL: Hurd sun_path に 14byte の NUL: FreeBSD, Darwin, Debian GNU/kFreeBSD sun_path に 104byte の NUL: NetBSD ENOTCONN: Haiku EINVAL: Minix 13

バリエーション豊かな挙動 (4) ソケットを bind せずに connect したとき accept が返すアドレスは だいたい getsockname した結果と同じ でも DragonFly BSD, OpenBSD, MirOS, SunOS は空の sockaddr ではなく sun_path に 14byte の NUL Haiku は ENOTCONN でなく "\0002b1" というよ うな通し番号 Minix は EINVAL でなくサーバソケットのアドレ ス Cygwin は終端の後の NUL を書き込まない 14

バリエーション豊かな挙動 (5) パスの NUL 終端の後にゴミを書き そのゴミも含めた長さで bind して getsockname すると ゴミも含めてそのまま返ってくる : 4.4BSD, SunOS ゴミは NUL に書き潰されるが長さはそのまま : OpenBSD 5.1 ゴミは NUL に書き潰され 長さは sizeof(sun_path) に伸ばされる : OpenBSD 5.2 ゴミが捨てられ 最初の NUL までに切り詰めら れる : Haiku, Linux, Cygwin 絶対パスになり ゴミは捨てられる : Minix 15

バリエーション豊かな挙動 (6) パスの NUL 終端の後にゴミを書き そのゴミも含めた長さで connect した後 getpeername すると SunOS: ゴミも含めて返ってくる (Cygwin は NUL までに切り詰めるのでゴミは返ってこない ) sizeof(sun_path) よりも長いパスを bind 可能だった場合 getsockname などの結果は バッファには切り詰められた結果が書き込まれ 長さは本来の長さが返る : Darwin, SunOS, Linux 長さはバッファの長さになる : DragonFly BSD, NetBSD, MirOS 16

バリエーション豊かな挙動 (7) bind に NUL を含まない長さを与えた場合 getsockname すると そのままの長さ 内容が返ってくる : FreeBSD, Debian GNU/kFreeBSD, Darwin, DragonFly BSD, NetBSD, OpenBSD 5.1, MirOS NUL がひとつ追加されて返ってくる : Linux, SunOS sun_path の残りが NUL で埋め尽くされて返っ てくる : OpenBSD 5.2 Buffer over read してる? Haiku, Minix, Cygwin 17

バリエーション豊かな挙動 (8) sun_len についてはとくにバリエーションは 無い模様 : アプリケーションが指定した値をカーネルは無視 する カーネルがアプリケーションに渡すときは長さを 書き込む Haiku は SOCK_DGRAM だと socket が EAFNOSUPPORT Minix は SOCK_DGRAM では connect が EINVAL 18

どこまで長いパスを受け入れるか ccccc\0 というように c を繰り返した場合 (NUL 終端も含めた長さを指定した場合 ) 104: FreeBSD, OpenBSD 108: Linux, Cygwin 111: Minix 126: Haiku 23?: MirOS (kernel panic) 253: Darwin, DragonFly BSD, NetBSD 256: SunOS, Hurd ( ファイル名の限界 ) 19

どこまで長いパスを受け入れるか./././././././ab\0 というように./ を繰り返した場合 (NUL 終端も含めた長さを指定した場合 ) 104: FreeBSD, OpenBSD 108: Linux, Cygwin 126: Haiku 128: Minix 235: MirOS 253: Darwin, DragonFly BSD, NetBSD 1024: SunOS 1027: Hurd (./ の繰り返し 512 回の限界 ) 20

どこまで長いパスを受け入れるか NUL 終端をしない長さを与えた場合 疲れたので省略 21

Buffer Over Read Cygwin: bind() が引数の長さを無視して NUL 文字を 探す Hurd: connect() が引数の長さを無視して NUL 文字を探す (bind() は引数で与えた長さまでしか見ない ) Haiku: bind に NUL 終端されていないパスを与えると 指定した長さだけ kernel 空間にコピーした後 その長さを無視して NUL 文字を探す Minix 3.2.1: NUL 終端の後にゴミがあると bind が失 敗する Minix 3.2.1: 上記の修正後でも引数で指定した長さを22 無視して sizeof(sun_path) だけコピーする

その他の問題 Cygwin: connect と accept が同期する Minix: connect しただけでは accept が終わらない クライアントが終わってもサーバに EOF が伝わらない NetBSD: クライアントが close した後にサーバが accept すると クライアントのアドレスがくるべきところにサーバのアドレスとゴミがくる MirOS: 234 バイト (NUL 込み ) のパスで bind して getsockname すると kernel panic ( もっと条件がある?) 23

その他の問題 (2) Cygwin: Unix domain の SOCK_STREAM ソケットで accept や getpeername が空のアドレスを返す Cygwin: Unix domain の SOCK_DGRAM ソケットで recvfrom が AF_INET なアドレスを返す Debian GNU/kFreeBSD: 長すぎるパスを与えてもエラーにならず 単に 104 バイトで切り落とされる 24

その他の問題 (3) Minix: すでに存在するファイルやディレクトリに Unix domain socket を bind できる 25

エピソード Cygwin の Buffer over read を指摘した Cygwin 開発者は Buffer over read を直すついで に NUL 終端を必須にした (POSIX は NUL 終端必須 ) スナップショットが出たら D-Bus の開発者がバグレポートを送ってきた NUL 終端していなかったのだろう ( おそらく ) NUL 終端を必須にはしなくなった 26

現実と仕様の乖離 POSIX では sun_path はパス名で パス名は定義と して NUL 終端するもの (POSIX2001) a pathname consists of, at most, {PATH_MAX} bytes, including the terminating null byte. POSIX では構造体の長さを指定することを想定 傍証 1: bind() の項のサンプル (POSIX2008) 傍証 2: sockaddr_un のフィールドの順序が決まっていない ( 現実的には変えられないけれど ) The <sys/un.h> header shall define the sockaddr_un structure, which shall include at least the following members: 4.3BSD のドキュメントでは NUL 直前までの長さを指定すると明確に書いてある (1986) きれいな仕様を決めたが現実には勝てなかった? 27

IPv4 もちょっとテストした struct sockaddr_in にはパディングがある getsockname などでカーネルからアドレスを得たとき パディング部分にゴミが入る OS がある : Hurd, Haiku 28

教訓とまとめ 仕様が仕様を決めるわけではない API デザインは重要 デファクト仕様を見抜くのは難しいひどい API を使用するときは気をつけないといけない いくら仕様がひどくても Buffer over read は許されないと思う ( 情報漏洩になるかも?) しかし終端の定義の違いと言われると困る 寛大な仕様で多様性を育てるのは不幸 いくつか開発元にレポートした : Cygwin, Hurd, Haiku, Minix, NetBSD, MirOS, Debian GNU/kFreeBSD 29