[インデックス 10434] ファイルの概要
このドキュメントは、Go言語のsyscall
パッケージにおけるOpenBSD固有のバグ修正に関するコミット(インデックス10434)について詳細に解説します。
コミット
このコミットは、OpenBSD 5.0以降で修正された特定のバグに対するワークアラウンドを実装しています。具体的には、kern.hostname
またはkern.domainname
の要求時にoldp
にnil
値が渡された場合、長さがゼロとして返される問題に対処しています。このケースに遭遇した場合、MAXHOSTNAMELEN
(256)の長さを利用するように変更されています。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9b571a31200ffccad327cefb48944a3b88494bcd
元コミット内容
commit 9b571a31200ffccad327cefb48944a3b88494bcd
Author: Joel Sing <jsing@google.com>
Date: Fri Nov 18 01:52:39 2011 +1100
syscall: hostname/domainname fix for openbsd
Work around a bug that was fixed after OpenBSD 5.0 - a request for
kern.hostname or kern.domainname with a nil value for oldp will result
in a length of zero being returned. If we hit this case use a length
of MAXHOSTNAMELEN (256).
R=golang-dev, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/5408041
---
src/pkg/syscall/syscall_bsd.go | 11 ++++++++++-\
1 file changed, 10 insertions(+), 1 deletion(-)\
diff --git a/src/pkg/syscall/syscall_bsd.go b/src/pkg/syscall/syscall_bsd.go
index 65ac1e08da..163232ad48 100644
--- a/src/pkg/syscall/syscall_bsd.go
+++ b/src/pkg/syscall/syscall_bsd.go
@@ -559,7 +559,16 @@ func Sysctl(name string) (value string, err error) {
\treturn \"\", err
}\n \tif n == 0 {\n-\t\treturn \"\", nil\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 OS == \"openbsd\" && (value == \"kern.hostname\" || value == \"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}\n \n \t// Read into buffer of that size.\n```
## 変更の背景
この変更は、OpenBSD 5.0以降で修正された特定のカーネルバグに対するワークアラウンドとして導入されました。Go言語の`syscall`パッケージは、オペレーティングシステムの低レベルな機能にアクセスするためのインターフェースを提供します。`Sysctl`関数は、システムコントロールインターフェースを介してカーネル情報を取得するために使用されます。
OpenBSDの特定のバージョンでは、`kern.hostname`や`kern.domainname`といったシステム情報を取得する際に、`sysctl`システムコールに`oldp`引数として`nil`(またはNULLポインタ)を渡すと、期待されるデータ長ではなくゼロが返されるというバグがありました。通常、`oldp`に`nil`を渡すのは、データの実際の長さを取得するためであり、その長さに基づいて適切なバッファを割り当ててから再度`sysctl`を呼び出すのが一般的なパターンです。しかし、このバグにより、正しい長さを取得できず、結果としてホスト名やドメイン名を取得できない問題が発生していました。
Goの`syscall`パッケージがこのバグのあるOpenBSDバージョンで正しく動作するようにするため、このワークアラウンドが実装されました。コミットメッセージには「OpenBSD 5.2リリース後に削除する」というTODOコメントがあり、これはこの修正が一時的なものであり、OpenBSDのカーネルバグが完全に修正された後に削除されるべきであることを示しています。
## 前提知識の解説
### `sysctl`システムコール
`sysctl`は、Unix系オペレーティングシステム(BSD系、Linuxなど)でカーネルのパラメータを動的に読み書きするためのシステムコールです。これにより、システム管理者やアプリケーションは、カーネルの動作に関する情報を取得したり、一部の動作を変更したりできます。
`sysctl`の一般的な使用方法は以下の通りです。
1. **データの長さを取得**: `oldp`引数に`NULL`(または`nil`)を渡し、`oldlenp`引数にポインタを渡すことで、取得したいデータの長さを`oldlenp`が指す変数に格納させます。
2. **データを取得**: 1で取得した長さに基づいてバッファを割り当て、そのバッファへのポインタを`oldp`に、バッファのサイズを`oldlenp`に渡して`sysctl`を再度呼び出します。
このコミットで対処されているバグは、1のステップで`oldp`に`nil`を渡した際に、`kern.hostname`や`kern.domainname`の場合に限り、`oldlenp`に正しい長さではなくゼロが返されるというものでした。
### `kern.hostname`と`kern.domainname`
これらは`sysctl`を通じてアクセスできるカーネルパラメータの一部です。
* `kern.hostname`: システムのホスト名(例: `mycomputer.example.com`)を保持します。
* `kern.domainname`: システムのドメイン名(例: `example.com`)を保持します。
これらの情報は、ネットワーク通信やシステム識別のために重要です。
### `MAXHOSTNAMELEN`
`MAXHOSTNAMELEN`は、ホスト名の最大長を定義する定数です。通常、この値は256バイトに設定されています。これは、ホスト名がこの長さを超えないことを保証するために使用されます。このコミットでは、バグによって長さがゼロと返された場合に、この定数を使ってホスト名の最大長を仮定し、バッファを確保しています。
### OpenBSD
OpenBSDは、セキュリティを重視して開発されているUnix系オペレーティングシステムです。厳格なコードレビューとセキュリティ監査が特徴で、多くのセキュリティ機能がデフォルトで有効になっています。このコミットで言及されているバグは、OpenBSDの特定のバージョンに存在していたものです。
## 技術的詳細
Go言語の`syscall`パッケージ内の`Sysctl`関数は、`sysctl`システムコールをラップしています。この関数は、指定された`name`(例: "kern.hostname")に対応するカーネルパラメータの`value`を取得します。
コミット前のコードでは、`sysctl`システムコールを呼び出した後、返された長さ`n`が`0`の場合、エラーではなく空文字列を返していました。これは、通常、データが存在しないか、取得できないことを意味します。
```go
if n == 0 {
return "", nil
}
しかし、OpenBSDのバグにより、kern.hostname
やkern.domainname
の場合にoldp
がnil
だと、データは存在するにもかかわらずn
が0
と返されてしまう問題がありました。このため、GoのSysctl
関数は、ホスト名やドメイン名を取得できないと誤って判断していました。
このコミットでは、このn == 0
の条件に以下のワークアラウンドを追加しています。
OS
が"openbsd"
であるかを確認します。- 取得しようとしている
value
が"kern.hostname"
または"kern.domainname"
であるかを確認します。 - 上記の条件がすべて真である場合、
n
をMAXHOSTNAMELEN
(256)に設定します。これにより、後続の処理でホスト名またはドメイン名を格納するのに十分なサイズのバッファが確保されるようになります。 - それ以外の場合は、以前と同様に空文字列を返します。
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 OS == "openbsd" && (value == "kern.hostname" || value == "kern.domainname") {
// MAXHOSTNAMELEN
n = 256
} else {
return "", nil
}
}
この修正により、OpenBSDのバグがあるバージョンでも、GoのSysctl
関数がkern.hostname
とkern.domainname
を正しく取得できるようになりました。TODO
コメントは、この修正が一時的なものであり、OpenBSDのカーネルが修正された後に削除されるべきであることを明確に示しています。
コアとなるコードの変更箇所
変更はsrc/pkg/syscall/syscall_bsd.go
ファイル内のSysctl
関数に集中しています。
--- a/src/pkg/syscall/syscall_bsd.go
+++ b/src/pkg/syscall/syscall_bsd.go
@@ -559,7 +559,16 @@ func Sysctl(name string) (value string, err error) {
\treturn \"\", err
}\n \tif n == 0 {\n-\t\treturn \"\", nil\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 OS == \"openbsd\" && (value == \"kern.hostname\" || value == \"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}\n \n \t// Read into buffer of that size.\
コアとなるコードの解説
変更されたコードブロックは、Sysctl
関数内でsysctl
システムコールが返したデータ長n
が0
である場合の処理を修正しています。
if n == 0 { ... }
:sysctl
システムコールが返したデータ長がゼロの場合の条件分岐です。// TODO(jsing): Remove after OpenBSD 5.2 release.
: このコメントは、このコードが一時的なワークアラウンドであり、OpenBSDの将来のバージョンでバグが修正された後に削除されるべきであることを示しています。// Work around a bug that was fixed after OpenBSD 5.0.
: OpenBSD 5.0以降で修正されたバグへの対処であることを説明しています。// The length for kern.hostname and kern.domainname is always
:kern.hostname
とkern.domainname
の長さが常に...// returned as 0 when a nil value is passed for oldp.
:oldp
にnil
値が渡されたときにゼロとして返されるというバグの具体的な内容を説明しています。if OS == "openbsd" && (value == "kern.hostname" || value == "kern.domainname") { ... }
: この条件式が、ワークアラウンドを適用する対象を特定しています。OS == "openbsd"
: 現在のオペレーティングシステムがOpenBSDであるかを確認します。Go言語のビルドシステムは、コンパイル時にGOOS
環境変数に基づいて適切なOS定数を設定します。(value == "kern.hostname" || value == "kern.domainname")
: 取得しようとしているカーネルパラメータがホスト名またはドメイン名であるかを確認します。
n = 256
: 上記の条件が満たされた場合、n
(データ長)をMAXHOSTNAMELEN
である256に強制的に設定します。これにより、後続のコードが256バイトのバッファを割り当て、ホスト名またはドメイン名を読み取ろうとします。else { return "", nil }
: 上記のOpenBSDの特定のバグに該当しない場合は、以前と同様に空文字列を返します。これは、本当にデータが存在しないか、他の理由で長さがゼロになった場合に対応します。
この変更により、Goのsyscall
パッケージは、OpenBSDの特定のバージョンにおけるsysctl
のバグを透過的に回避し、ホスト名とドメイン名の取得を信頼性高く行えるようになりました。
関連リンク
- Go言語の
syscall
パッケージのドキュメント: https://pkg.go.dev/syscall - OpenBSDの
sysctl
マニュアルページ (一般的な情報): https://man.openbsd.org/sysctl - Go言語の変更リスト (CL): https://golang.org/cl/5408041
参考にした情報源リンク
- Go言語のソースコード (GitHub): https://github.com/golang/go
- OpenBSDの公式ウェブサイト: https://www.openbsd.org/
sysctl
に関する一般的な情報 (Wikipediaなど): https://ja.wikipedia.org/wiki/SysctlMAXHOSTNAMELEN
に関する情報 (Unix系システムのヘッダファイル): 通常、<sys/param.h>
や<limits.h>
などで定義されています。- OpenBSDの特定の
sysctl
バグに関する情報 (Web検索): "OpenBSD sysctl kern.hostname nil oldp bug" などのキーワードで検索すると、関連するメーリングリストの議論やパッチ情報が見つかる場合があります。
[インデックス 10434] ファイルの概要
このドキュメントは、Go言語のsyscall
パッケージにおけるOpenBSD固有のバグ修正に関するコミット(インデックス10434)について詳細に解説します。
コミット
このコミットは、OpenBSD 5.0以降で修正された特定のバグに対するワークアラウンドを実装しています。具体的には、kern.hostname
またはkern.domainname
の要求時にoldp
にnil
値が渡された場合、長さがゼロとして返される問題に対処しています。このケースに遭遇した場合、MAXHOSTNAMELEN
(256)の長さを利用するように変更されています。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9b571a31200ffccad327cefb48944a3b88494bcd
元コミット内容
commit 9b571a31200ffccad327cefb48944a3b88494bcd
Author: Joel Sing <jsing@google.com>
Date: Fri Nov 18 01:52:39 2011 +1100
syscall: hostname/domainname fix for openbsd
Work around a bug that was fixed after OpenBSD 5.0 - a request for
kern.hostname or kern.domainname with a nil value for oldp will result
in a length of zero being returned. If we hit this case use a length
of MAXHOSTNAMELEN (256).
R=golang-dev, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/5408041
---
src/pkg/syscall/syscall_bsd.go | 11 ++++++++++-\
1 file changed, 10 insertions(+), 1 deletion(-)\
diff --git a/src/pkg/syscall/syscall_bsd.go b/src/pkg/syscall/syscall_bsd.go
index 65ac1e08da..163232ad48 100644
--- a/src/pkg/syscall/syscall_bsd.go
+++ b/src/pkg/syscall/syscall_bsd.go
@@ -559,7 +559,16 @@ func Sysctl(name string) (value string, err error) {
\treturn \"\", err
}\n \tif n == 0 {\n-\t\treturn \"\", nil\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 OS == \"openbsd\" && (value == \"kern.hostname\" || value == \"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}\n \n \t// Read into buffer of that size.\
変更の背景
この変更は、OpenBSD 5.0以降で修正された特定のカーネルバグに対するワークアラウンドとして導入されました。Go言語のsyscall
パッケージは、オペレーティングシステムの低レベルな機能にアクセスするためのインターフェースを提供します。Sysctl
関数は、システムコントロールインターフェースを介してカーネル情報を取得するために使用されます。
OpenBSDの特定のバージョンでは、kern.hostname
やkern.domainname
といったシステム情報を取得する際に、sysctl
システムコールにoldp
引数としてnil
(またはNULLポインタ)を渡すと、期待されるデータ長ではなくゼロが返されるというバグがありました。通常、oldp
にnil
を渡すのは、データの実際の長さを取得するためであり、その長さに基づいて適切なバッファを割り当ててから再度sysctl
を呼び出すのが一般的なパターンです。しかし、このバグにより、正しい長さを取得できず、結果としてホスト名やドメイン名を取得できない問題が発生していました。
Goのsyscall
パッケージがこのバグのあるOpenBSDバージョンで正しく動作するようにするため、このワークアラウンドが実装されました。コミットメッセージには「OpenBSD 5.2リリース後に削除する」というTODOコメントがあり、これはこの修正が一時的なものであり、OpenBSDのカーネルバグが完全に修正された後に削除されるべきであることを示しています。
前提知識の解説
sysctl
システムコール
sysctl
は、Unix系オペレーティングシステム(BSD系、Linuxなど)でカーネルのパラメータを動的に読み書きするためのシステムコールです。これにより、システム管理者やアプリケーションは、カーネルの動作に関する情報を取得したり、一部の動作を変更したりできます。
sysctl
の一般的な使用方法は以下の通りです。
- データの長さを取得:
oldp
引数にNULL
(またはnil
)を渡し、oldlenp
引数にポインタを渡すことで、取得したいデータの長さをoldlenp
が指す変数に格納させます。 - データを取得: 1で取得した長さに基づいてバッファを割り当て、そのバッファへのポインタを
oldp
に、バッファのサイズをoldlenp
に渡してsysctl
を再度呼び出します。
このコミットで対処されているバグは、1のステップでoldp
にnil
を渡した際に、kern.hostname
やkern.domainname
の場合に限り、oldlenp
に正しい長さではなくゼロが返されるというものでした。
kern.hostname
とkern.domainname
これらはsysctl
を通じてアクセスできるカーネルパラメータの一部です。
kern.hostname
: システムのホスト名(例:mycomputer.example.com
)を保持します。kern.domainname
: システムのドメイン名(例:example.com
)を保持します。
これらの情報は、ネットワーク通信やシステム識別のために重要です。
MAXHOSTNAMELEN
MAXHOSTNAMELEN
は、ホスト名の最大長を定義する定数です。通常、この値は256バイトに設定されています。これは、ホスト名がこの長さを超えないことを保証するために使用されます。このコミットでは、バグによって長さがゼロと返された場合に、この定数を使ってホスト名の最大長を仮定し、バッファを確保しています。
OpenBSD
OpenBSDは、セキュリティを重視して開発されているUnix系オペレーティングシステムです。厳格なコードレビューとセキュリティ監査が特徴で、多くのセキュリティ機能がデフォルトで有効になっています。このコミットで言及されているバグは、OpenBSDの特定のバージョンに存在していたものです。
技術的詳細
Go言語のsyscall
パッケージ内のSysctl
関数は、sysctl
システムコールをラップしています。この関数は、指定されたname
(例: "kern.hostname")に対応するカーネルパラメータのvalue
を取得します。
コミット前のコードでは、sysctl
システムコールを呼び出した後、返された長さn
が0
の場合、エラーではなく空文字列を返していました。これは、通常、データが存在しないか、取得できないことを意味します。
if n == 0 {
return "", nil
}
しかし、OpenBSDのバグにより、kern.hostname
やkern.domainname
の場合にoldp
がnil
だと、データは存在するにもかかわらずn
が0
と返されてしまう問題がありました。このため、GoのSysctl
関数は、ホスト名やドメイン名を取得できないと誤って判断していました。
このコミットでは、このn == 0
の条件に以下のワークアラウンドを追加しています。
OS
が"openbsd"
であるかを確認します。- 取得しようとしている
value
が"kern.hostname"
または"kern.domainname"
であるかを確認します。 - 上記の条件がすべて真である場合、
n
をMAXHOSTNAMELEN
(256)に設定します。これにより、後続の処理でホスト名またはドメイン名を格納するのに十分なサイズのバッファが確保されるようになります。 - それ以外の場合は、以前と同様に空文字列を返します。
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 OS == "openbsd" && (value == "kern.hostname" || value == "kern.domainname") {
// MAXHOSTNAMELEN
n = 256
} else {
return "", nil
}
}
この修正により、OpenBSDのバグがあるバージョンでも、GoのSysctl
関数がkern.hostname
とkern.domainname
を正しく取得できるようになりました。TODO
コメントは、この修正が一時的なものであり、OpenBSDのカーネルが修正された後に削除されるべきであることを明確に示しています。
コアとなるコードの変更箇所
変更はsrc/pkg/syscall/syscall_bsd.go
ファイル内のSysctl
関数に集中しています。
--- a/src/pkg/syscall/syscall_bsd.go
+++ b/src/pkg/syscall/syscall_bsd.go
@@ -559,7 +559,16 @@ func Sysctl(name string) (value string, err error) {
\treturn \"\", err
}\n \tif n == 0 {\n-\t\treturn \"\", nil\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 OS == \"openbsd\" && (value == \"kern.hostname\" || value == \"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}\n \n \t// Read into buffer of that size.\
コアとなるコードの解説
変更されたコードブロックは、Sysctl
関数内でsysctl
システムコールが返したデータ長n
が0
である場合の処理を修正しています。
if n == 0 { ... }
:sysctl
システムコールが返したデータ長がゼロの場合の条件分岐です。// TODO(jsing): Remove after OpenBSD 5.2 release.
: このコメントは、このコードが一時的なワークアラウンドであり、OpenBSDの将来のバージョンでバグが修正された後に削除されるべきであることを示しています。// Work around a bug that was fixed after OpenBSD 5.0.
: OpenBSD 5.0以降で修正されたバグへの対処であることを説明しています。// The length for kern.hostname and kern.domainname is always
:kern.hostname
とkern.domainname
の長さが常に...// returned as 0 when a nil value is passed for oldp.
:oldp
にnil
値が渡されたときにゼロとして返されるというバグの具体的な内容を説明しています。if OS == "openbsd" && (value == "kern.hostname" || value == "kern.domainname") { ... }
: この条件式が、ワークアラウンドを適用する対象を特定しています。OS == "openbsd"
: 現在のオペレーティングシステムがOpenBSDであるかを確認します。Go言語のビルドシステムは、コンパイル時にGOOS
環境変数に基づいて適切なOS定数を設定します。(value == "kern.hostname" || value == "kern.domainname")
: 取得しようとしているカーネルパラメータがホスト名またはドメイン名であるかを確認します。
n = 256
: 上記の条件が満たされた場合、n
(データ長)をMAXHOSTNAMELEN
である256に強制的に設定します。これにより、後続のコードが256バイトのバッファを割り当て、ホスト名またはドメイン名を読み取ろうとします。else { return "", nil }
: 上記のOpenBSDの特定のバグに該当しない場合は、以前と同様に空文字列を返します。これは、本当にデータが存在しないか、他の理由で長さがゼロになった場合に対応します。
この変更により、Goのsyscall
パッケージは、OpenBSDの特定のバージョンにおけるsysctl
のバグを透過的に回避し、ホスト名とドメイン名の取得を信頼性高く行えるようになりました。
関連リンク
- Go言語の
syscall
パッケージのドキュメント: https://pkg.go.dev/syscall - OpenBSDの
sysctl
マニュアルページ (一般的な情報): https://man.openbsd.org/sysctl - Go言語の変更リスト (CL): https://golang.org/cl/5408041
参考にした情報源リンク
- Go言語のソースコード (GitHub): https://github.com/golang/go
- OpenBSDの公式ウェブサイト: https://www.openbsd.org/
sysctl
に関する一般的な情報 (Wikipediaなど): https://ja.wikipedia.org/wiki/SysctlMAXHOSTNAMELEN
に関する情報 (Unix系システムのヘッダファイル): 通常、<sys/param.h>
や<limits.h>
などで定義されています。- OpenBSDの特定の
sysctl
バグに関する情報 (Web検索): "OpenBSD sysctl kern.hostname nil oldp bug" などのキーワードで検索しましたが、この特定のバグに関する直接的な公開情報は見つかりませんでした。これは、バグが非常に限定的であったか、あるいは修正がマイナーリリースに含まれたため、広く文書化されなかった可能性を示唆しています。