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

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

このコミットは、Go言語のsyscallパッケージにおけるOpenBSD固有のsysctlワークアラウンドを削除するものです。GoがOpenBSD 5.1より前のバージョンをサポートしなくなったため、OpenBSD 5.0以前のバージョンで必要とされていた特定のsysctl呼び出しに関するバグ回避策が不要になりました。

コミット

  • コミットハッシュ: e5f2662c25dbdf2ed258867964e424f00f7a9cb8
  • Author: Joel Sing jsing@google.com
  • Date: Fri Apr 27 01:45:15 2012 +1000

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

https://github.com/golang/go/commit/e5f2662c25dbdf2ed258867964e424f00f7a9cb8

元コミット内容

syscall: remove sysctl workaround for openbsd

Now that Go will no longer work on OpenBSD versions prior to 5.1,
remove the sysctl workaround that was needed for 5.0 and earlier.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/6116050

変更の背景

この変更の背景には、Go言語のOpenBSDサポートポリシーの変更があります。以前のGoのバージョンでは、OpenBSD 5.0以前のバージョンでsysctlシステムコールを使用する際に特定のバグが存在していました。具体的には、kern.hostnamekern.domainnameといったシステム情報を取得するためにsysctlを呼び出す際、古いOpenBSDバージョンでは、バッファサイズを問い合わせるためにnilポインタを渡すと、常にサイズが0として返されるという問題がありました。

この問題を回避するため、Goのsyscallパッケージには、OpenBSD 5.0以前のバージョンでのみ適用される特別なワークアラウンドが実装されていました。このワークアラウンドは、kern.hostnamekern.domainnameに対してsysctlを呼び出す際に、返されるサイズが0であっても、固定のMAXHOSTNAMELEN(256バイト)をバッファサイズとして仮定するというものでした。

しかし、GoがOpenBSD 5.1より前のバージョンをサポート対象外としたため、この古いOpenBSDバージョンに特化したバグ回避策は不要となりました。Goの新しいバージョンは、OpenBSD 5.1以降のバージョンで実行されることを前提としており、これらのバージョンではsysctlのバグが修正されているため、特別な処理は必要ありません。このコミットは、コードベースのクリーンアップと、不要になったレガシーコードの削除を目的としています。

前提知識の解説

sysctl

sysctlは、Unix系オペレーティングシステム(特にBSD系OS)でシステムパラメータを動的に参照または設定するためのメカニズムです。システムパラメータには、カーネルのバージョン、ホスト名、ネットワーク設定、メモリ情報など、多岐にわたる情報が含まれます。 sysctlシステムコールは通常、以下のような形式で呼び出されます。

int sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
  • name: 取得または設定したいパラメータの識別子(整数配列)。
  • namelen: name配列の要素数。
  • oldp: パラメータの現在の値が格納されるバッファへのポインタ。
  • oldlenp: oldpバッファのサイズへのポインタ。通常、最初にoldpNULLoldlenpNULLでないポインタとして呼び出し、必要なバッファサイズを取得します。その後、適切なサイズのバッファを割り当てて再度呼び出します。
  • newp: パラメータの新しい値へのポインタ(設定する場合)。
  • newlen: newpバッファのサイズ(設定する場合)。

このコミットで問題となっていたのは、oldpNULLを渡し、oldlenpで必要なサイズを取得する際の挙動が、OpenBSD 5.0以前で正しくなかった点です。

OpenBSD

OpenBSDは、セキュリティを重視して開発されているUnix系オペレーティングシステムです。厳格なコードレビューとセキュリティ機能の実装で知られています。Go言語のようなクロスプラットフォーム言語は、様々なOSで動作するように設計されており、それぞれのOSのシステムコールやAPIの違いを吸収するためのラッパー(この場合はsyscallパッケージ)を提供しています。OSのバージョンアップに伴い、システムコールの挙動が改善されることがあり、それに合わせてGoのコードも更新されることがあります。

Go言語のsyscallパッケージ

Go言語の標準ライブラリには、オペレーティングシステムの低レベルなシステムコールにアクセスするためのsyscallパッケージが含まれています。このパッケージは、OS固有のシステムコールをGoの関数として抽象化し、GoプログラムからOSの機能を利用できるようにします。異なるOS間での互換性を保つため、syscallパッケージ内にはOSごとの実装ファイル(例: syscall_bsd.gosyscall_linux.goなど)が存在し、runtime.GOOSなどのビルドタグによって適切なファイルがコンパイル時に選択されます。

技術的詳細

変更が加えられたのはsrc/pkg/syscall/syscall_bsd.goファイルです。このファイルは、BSD系のOS(OpenBSD、FreeBSD、NetBSDなど)向けのsyscallパッケージの実装を含んでいます。

問題となっていたのは、Sysctl関数の内部で、sysctlシステムコールを呼び出して必要なバッファサイズを取得する部分でした。

元のコードでは、sysctlシステムコールをoldpnilを渡して呼び出し、n(必要なバッファサイズ)を取得していました。もしnが0だった場合、通常は値がないことを意味しますが、OpenBSD 5.0以前ではkern.hostnamekern.domainnameに対してこの呼び出しを行うと、バグにより常にnが0として返されていました。

このため、元のコードには以下のワークアラウンドが含まれていました。

		if n == 0 {
			// TODO(jsing): Remove after OpenBSD 5.2 release.
			// Work around a bug that was fixed after OpenBSD 5.0.
			// The length for kern.hostname and kern.domainname is always
			// returned as 0 when a nil value is passed for oldp.
			if runtime.GOOS == "openbsd" && (name == "kern.hostname" || name == "kern.domainname") {
				// MAXHOSTNAMELEN
				n = 256
			} else {
				return "", nil
			}
		}

このコードは、nが0の場合に、現在のOSがOpenBSDであり、かつnamekern.hostnameまたはkern.domainnameである場合に限り、nを固定値の256(MAXHOSTNAMELENに相当)に設定していました。これは、OpenBSD 5.0以前のバグを回避し、これらのシステムパラメータの取得に必要なバッファサイズを強制的に設定するためのものでした。

GoがOpenBSD 5.1以降のみをサポートするようになったため、このバグはもはやGoの実行環境では発生しません。したがって、この特定のOpenBSDバージョンに特化したワークアラウンドは不要となり、削除されました。

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

--- a/src/pkg/syscall/syscall_bsd.go
+++ b/src/pkg/syscall/syscall_bsd.go
@@ -13,7 +13,6 @@
 package syscall
 
 import (
-\t"runtime"
 	"unsafe"
 )
 
@@ -553,16 +552,7 @@ func Sysctl(name string) (value string, err error) {
 	\treturn "", err
 	}\n \tif n == 0 {\n-\t\t// TODO(jsing): Remove after OpenBSD 5.2 release.\n-\t\t// Work around a bug that was fixed after OpenBSD 5.0.\n-\t\t// The length for kern.hostname and kern.domainname is always\n-\t\t// returned as 0 when a nil value is passed for oldp.\n-\t\tif runtime.GOOS == "openbsd" && (name == "kern.hostname" || name == "kern.domainname") {\n-\t\t\t// MAXHOSTNAMELEN\n-\t\t\tn = 256\n-\t\t} else {\n-\t\t\treturn "", nil\n-\t\t}\n+\t\treturn "", nil\n \t}\n \n \t// Read into buffer of that size.\n```

## コアとなるコードの解説

このコミットでは、`src/pkg/syscall/syscall_bsd.go`ファイルから以下の変更が行われました。

1.  **`runtime`パッケージのインポート削除**:
    `runtime.GOOS`を使用して現在のOSがOpenBSDであるかを判定していたため、`runtime`パッケージがインポートされていました。ワークアラウンドの削除に伴い、この判定が不要になったため、`runtime`パッケージのインポートも削除されました。

    ```diff
    -	"runtime"
    ```

2.  **OpenBSD固有の`sysctl`ワークアラウンドの削除**:
    `Sysctl`関数内の、`n`が0の場合の条件分岐が簡素化されました。以前は、`n`が0の場合にOpenBSDの特定のバージョンでのバグを回避するための特別なロジックが含まれていましたが、これが完全に削除され、`n`が0の場合は単に空文字列と`nil`エラーを返すようになりました。

    ```diff
    -		if n == 0 {
    -			// TODO(jsing): Remove after OpenBSD 5.2 release.
    -			// Work around a bug that was fixed after OpenBSD 5.0.
    -			// The length for kern.hostname and kern.domainname is always
    -			// returned as 0 when a nil value is passed for oldp.
    -			if runtime.GOOS == "openbsd" && (name == "kern.hostname" || name == "kern.domainname") {
    -				// MAXHOSTNAMELEN
    -				n = 256
    -			} else {
    -				return "", nil
    -			}
    -		}
    +		return "", nil
    ```

この変更により、`Sysctl`関数はよりシンプルになり、OpenBSDの古いバージョンに起因する特殊なケースを考慮する必要がなくなりました。これは、GoがサポートするOpenBSDの最小バージョンが引き上げられたことによる直接的な結果です。

## 関連リンク

- Go CL 6116050: [https://golang.org/cl/6116050](https://golang.org/cl/6116050)

## 参考にした情報源リンク

- `sysctl` man page (一般的な情報): [https://man.openbsd.org/sysctl.2](https://man.openbsd.org/sysctl.2) (OpenBSDのバージョンによって内容が異なる場合があります)
- Go言語の`syscall`パッケージに関するドキュメント (Goの公式ドキュメント): [https://pkg.go.dev/syscall](https://pkg.go.dev/syscall)
- OpenBSDのリリースノートや変更履歴 (OpenBSDのバージョンごとの変更点を確認するため): [https://www.openbsd.org/releases.html](https://www.openbsd.org/releases.html) (具体的なバグ修正のコミットやリリースノートは、当時の情報を追跡する必要がありますが、一般的な情報源として)
- Go言語のOpenBSDサポートに関する議論やメーリングリストのアーカイブ (当時のGoコミュニティでの議論を追跡するため): [https://groups.google.com/g/golang-dev](https://groups.google.com/g/golang-dev) (当時の議論を検索する必要がある)