Perl Hackers Hub

第46回 Perl 5.26で変わること(1)

この記事を読むのに必要な時間:およそ 4 分

本連載では第一線のPerlハッカーが回替わりで執筆していきます。今回のハッカーはcharsbarこと石垣憲一さんで,テーマは「Perl 5.26で変わること」です。

Perl 5.26リリース

去る2017年5月30日にPerl 5.26がリリースされました。これは1987年にPerl 1.0が生まれてから30年,モダンPerl運動のきっかけとなったPerl 5.10が2007年に生まれてから10年という節目のリリースです。2016年春に新たにパンプキン注1に就任したSawyer X氏のリードのもとでリリースされる最初の安定版注2でもあります。

Perl 5はかれこれ20年以上も同じメジャーバージョンを使い続けていることからも察せられるように,後方互換性が比較的よく保たれている言語です。それでも,節目節目では新機能の追加とともに多かれ少なかれ互換性が失われるような変更が行われてきました。その多くはバグと言っても差し支えないような細かな挙動の変更や実験的な機能に関するものですが,2016年12月から2017年7月にかけて札幌,大阪,福岡で開催されたYAPCYet Another Perl Conferenceなどで既報のとおり,Perl 5.26では一部の人に非常に大きな影響を及ぼしそうな非互換性がいくつか入っています。

Perl 5.26で何が変わったかは,5.26付属のperldeltaという文書にまとまっています。

本稿では,まずPerl 5.26の最大の変更点である特殊変数@INCからカレントディレクトリが削除された経緯とその対策を説明し,そのあと,細かな互換性の問題やPerl 5.26の新しい機能を紹介します。

注1)
Perl 5本体の開発チーム内の意見調整や,リリースマネージャーなどを担当するリーダー役です。
注2)
Perl 5は,2010年にリリースされたPerl 5.12以降,修正の多寡によらず,毎年春に偶数のマイナーバージョンを持つ安定版をリリースすることになっています(マイナーバージョンが奇数の開発版は,安定版リリース前のコードフリーズの時期を除いて毎月リリースされます)⁠今回リリースされたPerl 5.26.0は,2016年5月にリリースされたPerl 5.25.0から2017年4月にリリースされたPerl 5.25.12までの修正内容をまとめたものです。

@INCからカレントディレクトリが削除

Perlはバージョン3の時代である1990年から,ファイルやモジュールの呼び出し元を指定する特殊変数@INCの末尾に,カレントディレクトリを表す.を保持していました。20世紀末のCGIスクリプトでは歌代和正氏が作成したjcode.plというライブラリがよく利用されましたが,次のようなコードを書いて,CGIスクリプトの置かれているディレクトリにjcode.plというファイルを設置するだけで期待したとおりに動作したのは,@INCの末尾にカレントディレクトリが含まれていたからです。

# ほかの場所にインストールされていなければ
# CGIスクリプトと同じディレクトリにある
# jcode.plを読み込む
require "jcode.pl";

Perl 5.26では,セキュリティ上の理由でデフォルトの@INCから.が削除されました。上のコードはそのままではもう期待どおりの動作はしません注3)⁠

注3)
jcode.plはPerl 5.22で非互換になった機能を利用しているため,そもそもそのままではPerl 5.26では動作しません。

何が問題だったのか

UNIX系OSの世界,とりわけシステム管理者の間では前世紀から,実行ファイルを検索するパスにカレントディレクトリが含まれているとセキュリティ的によろしくない,という議論がされてきました。たまたまそのディレクトリに何らかの実行ファイルが存在していた場合,タイプミスなどの意図しない理由でそのファイルが実行されてしまう恐れがあるためです。安全のためには,システム標準以外のコマンドを実行するときは,どのディレクトリにあるコマンドかを明示すべきです。

読み込んだ時点でなにがしかのコードが実行されてしまうという点では,スクリプト言語のライブラリ類も同じです。正規のインストールパスにはインストールされていないライブラリがたまたまカレントディレクトリに存在していた場合,ライブラリの検索パスにカレントディレクトリが含まれていると,場合によっては意図しない形でそのライブラリが読み込まれ,内部のコードが実行されてしまいます。これは,特に特権ユーザーでスクリプトを実行することの多いシステム管理者には歓迎できないことです。

Rubyの対応とPerlの初期の反応

そのため,たとえばRubyの世界では2010年8月にリリースされたバージョン1.9.2でロードパス$:からカレントディレクトリが削除されました

Perlの世界でも,同じく2010年8月に@INCからカレントディレクトリを削除する提案がされていたほかその2年後,Perl 5.16のリリースを間近に控えた2012年3月にも議論が再燃し,賛成反対合わせて都合40通ほどのメールが飛び交いました。ただ,20年も前から便利に使われ続けてきた仕様を変更することで,既存のモジュールやアプリケーションに大きな影響が出ることを心配する声が強かったことから,いずれも明確な結論は出ないまま議論は立ち消えになりました。

CVE-2016-1238とPerlの対応

この議論は2016年4月にまたも蒸し返されるのですが,今度は机上の空論ではなく実際に深刻な問題が発覚した─⁠─Debian GNU/Linux系ディストリビューションのパッケージ管理ツールが,実行中に誰でも読み書きできるディレクトリに移動したうえで内部的にPerlスクリプトを呼び出していたことから,共有サーバなどで悪意を持ったユーザーがそのディレクトリにしかけをすると容易にルート権限を奪える状態になっていた─⁠─ということで,これまでのような公開チャンネルではなく,セキュリティ問題を扱う非公開のメーリングリストで話が進んでいきます。

対策を取れば既存のモジュールやアプリケーションが壊れることはこれまでの議論からもわかっていたので,まずはそもそもPerl側が対策すべきか,またどこまで対策すべきかをすり合わせ,それからどう対応すれば影響を最小限にとどめられるか,関係者の間で議論されていきました。

公式にはCVE-2016-1238というIDで識別されるこの脆弱性に関する議論は1年近く続きました。その詳細は割愛しますが,最終的にはシステム管理用のスクリプトの安全性を保つのはスクリプトの作者の責任としたうえで,深刻な問題が起こる可能性を減らすため,Perl側でもデフォルトの@INCからカレントディレクトリが削られました。コアモジュールのうち特によく使われるものについては,モジュール側にも対策を施して古いPerlが入っている環境への対策としたうえで,CPANモジュールのインストールに支障が出ないようツールチェイン側にしかけが加えられました。また,この問題の影響を受けていることに気付かれづらいdo関数については,警告を出すことになりました。

著者プロフィール

石垣憲一(いしがきけんいち)

翻訳家兼プログラマ。歴史ネタ担当。最近は主にCPANツールチェーン界隈の片隅で活動中。

URL:http://d.hatena.ne.jp/charsbar/