Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 18072] ファイルの概要

このコミットは、Go言語のsyscallパッケージにおいて、Plan 9オペレーティングシステム上でのファイル名にスラッシュ(/)の使用を禁止する変更を導入しています。これにより、ファイル名の解析やセキュリティに関する潜在的な問題を防ぎ、Plan 9のファイルシステムセマンティクスとの整合性を高めています。

コミット

commit 674606503e716dbea89166d2df87e2ec887aa4da
Author: David du Colombier <0intro@gmail.com>
Date:   Thu Dec 19 00:58:23 2013 +0100

    syscall: disallow slashes in file names on Plan 9
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/43480050

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/674606503e716dbea89166d2df87e2ec887aa4da

元コミット内容

syscall: disallow slashes in file names on Plan 9

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/43480050

変更の背景

この変更の背景には、Plan 9オペレーティングシステムのファイルシステムにおける特殊なパスの扱いがあります。Unix系システムではスラッシュ(/)がディレクトリの区切り文字として厳密に機能し、ファイル名自体にスラッシュを含めることは通常許可されません。しかし、Plan 9のファイルシステムプロトコルである9P(またはPlan 9 File Protocol)では、ファイル名にスラッシュを含めることが技術的には可能であり、これが予期せぬ挙動やセキュリティ上の脆弱性を引き起こす可能性がありました。

Go言語のsyscallパッケージは、OS固有のシステムコールへの低レベルなインターフェースを提供します。Plan 9をターゲットとする場合、Goプログラムがファイルシステム操作を行う際に、Plan 9のセマンティクスに厳密に従う必要があります。ファイル名にスラッシュが含まれていると、パスの解決時に混乱が生じたり、意図しないファイルがアクセスされたりするリスクがありました。このコミットは、このような潜在的な問題を未然に防ぎ、GoプログラムがPlan 9上でより堅牢かつ安全に動作するようにするためのものです。

前提知識の解説

Plan 9 from Bell Labs

Plan 9 from Bell Labsは、ベル研究所で開発された分散オペレーティングシステムです。Unixの設計思想をさらに推し進め、すべてのリソース(ファイル、デバイス、ネットワーク接続など)をファイルとして表現し、9Pプロトコルを通じてアクセスするという徹底した「すべてはファイル」の原則に基づいています。

9Pプロトコル

9P(Plan 9 File Protocol)は、Plan 9システムにおけるクライアントとサーバー間の通信プロトコルです。ファイルシステムのリソースへのアクセスを抽象化し、ネットワーク越しに透過的にファイルシステムを共有することを可能にします。9Pでは、ファイルやディレクトリは「Qid」(Qualified ID)と呼ばれるユニークな識別子によって参照されます。

ファイル名とパスのセマンティクス

Unix系システムでは、ファイル名にスラッシュを含めることはできません。スラッシュはパスの区切り文字として予約されています。例えば、/home/user/document.txtというパスでは、homeuserはディレクトリ名、document.txtはファイル名です。ファイル名自体に/が含まれると、パスの解釈が曖昧になり、セキュリティ上の問題(例: パストラバーサル攻撃)につながる可能性があります。

Plan 9のファイルシステムでは、ファイル名にスラッシュを含めることがプロトコル上は可能ですが、これは通常推奨されません。なぜなら、多くのアプリケーションやツールがスラッシュをパスの区切り文字として解釈するため、予期せぬ動作を引き起こす可能性があるからです。このコミットは、GoのsyscallパッケージがPlan 9のファイルシステムとやり取りする際に、この潜在的な不整合を解消することを目的としています。

技術的詳細

このコミットは、src/pkg/syscall/dir_plan9.goファイルに修正を加えています。このファイルは、Plan 9固有のディレクトリ操作やファイル情報の構造体(Dir)を扱うためのGoのシステムコールラッパーの一部です。

具体的には、Dir構造体をバイト列にマーシャル(シリアライズ)するMarshalメソッドに、ファイル名(d.Name)にスラッシュが含まれていないかをチェックするロジックが追加されました。

  1. エラーの追加: ErrBadNameという新しいエラーが定義されました。これは「ファイル名に不正な文字が含まれている」ことを示すエラーです。
    var (
        ErrShortStat = errors.New("stat buffer too short")
        ErrBadStat   = errors.New("malformed stat buffer")
        ErrBadName   = errors.New("bad character in file name") // <-- 追加
    )
    
  2. ファイル名チェックの追加: Dir.Marshalメソッド内で、d.Nameの各文字をループし、スラッシュ(/)が見つかった場合に即座にErrBadNameエラーを返して処理を中断するようになりました。
    for _, c := range d.Name {
        if c == '/' {
            return n, ErrBadName
        }
    }
    

この変更により、GoプログラムがPlan 9のファイルシステムに対して、ファイル名にスラッシュを含むDir構造体をマーシャルしようとすると、この新しいエラーが返されるようになります。これにより、不正なファイル名がファイルシステムに書き込まれることを防ぎ、パスの解釈に関する問題を未然に防ぐことができます。

コアとなるコードの変更箇所

変更はsrc/pkg/syscall/dir_plan9.goファイルに集中しています。

--- a/src/pkg/syscall/dir_plan9.go
+++ b/src/pkg/syscall/dir_plan9.go
@@ -11,6 +11,7 @@ import "errors"
 var (
 	ErrShortStat = errors.New("stat buffer too short")
 	ErrBadStat   = errors.New("malformed stat buffer")
+\tErrBadName   = errors.New("bad character in file name")
 )
 
 // A Qid represents a 9P server\'s unique identification for a file.
@@ -65,6 +66,12 @@ func (d *Dir) Marshal(b []byte) (n int, err error) {\
 \t\treturn n, ErrShortStat
 \t}\n \
+\tfor _, c := range d.Name {\
+\t\tif c == \'/\' {\
+\t\t\treturn n, ErrBadName
+\t\t}\n+\t}\n+\
 \tb = pbit16(b, uint16(n)-2)\
 \tb = pbit16(b, d.Type)\
 \tb = pbit32(b, d.Dev)\

コアとなるコードの解説

ErrBadNameの追加

ErrBadNameは、ファイル名に不正な文字が含まれていることを示す新しいエラー定数です。これにより、ファイル名検証の失敗を明確に区別できるようになりました。

Dir.Marshalメソッド内のループとチェック

Dir.Marshalメソッドは、Dir構造体の内容をPlan 9のファイルシステムプロトコル(9P)で定義されたバイト列形式に変換(マーシャル)する役割を担います。このバイト列は、ファイルシステムサーバーに送信され、ファイルやディレクトリのメタデータとして解釈されます。

追加されたコードブロックは以下の通りです。

for _, c := range d.Name {
    if c == '/' {
        return n, ErrBadName
    }
}
  • for _, c := range d.Name: これは、Dir構造体のNameフィールド(ファイル名を表す文字列)の各Unicodeコードポイント(rune)を反復処理します。
  • if c == '/': 各文字cがスラッシュ文字(/)であるかをチェックします。
  • return n, ErrBadName: もしスラッシュが見つかった場合、メソッドは直ちに現在のバイト数nと新しく定義されたErrBadNameエラーを返します。これにより、不正なファイル名を持つDir構造体がマーシャルされるのを防ぎ、その結果、Plan 9ファイルシステムに不正なファイル名が書き込まれることを防ぎます。

この変更は、GoのsyscallパッケージがPlan 9のファイルシステムと安全かつ一貫性のある方法で対話することを保証するための重要な防御策です。

関連リンク

参考にした情報源リンク

  • Go言語の公式リポジトリ: https://github.com/golang/go
  • Go言語のコードレビューシステム (Gerrit): https://go.dev/cl/43480050 (コミットの変更リスト)
  • Plan 9 from Bell Labsの概念に関する一般的な情報源 (例: Wikipedia, 技術記事など)