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

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

このドキュメントは、Go言語のsyscallパッケージにおけるOpenBSD固有のバグ修正に関するコミット(インデックス10434)について詳細に解説します。

コミット

このコミットは、OpenBSD 5.0以降で修正された特定のバグに対するワークアラウンドを実装しています。具体的には、kern.hostnameまたはkern.domainnameの要求時にoldpnil値が渡された場合、長さがゼロとして返される問題に対処しています。このケースに遭遇した場合、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.hostnamekern.domainnameの場合にoldpnilだと、データは存在するにもかかわらずn0と返されてしまう問題がありました。このため、GoのSysctl関数は、ホスト名やドメイン名を取得できないと誤って判断していました。

このコミットでは、このn == 0の条件に以下のワークアラウンドを追加しています。

  1. OS"openbsd"であるかを確認します。
  2. 取得しようとしているvalue"kern.hostname"または"kern.domainname"であるかを確認します。
  3. 上記の条件がすべて真である場合、nMAXHOSTNAMELEN(256)に設定します。これにより、後続の処理でホスト名またはドメイン名を格納するのに十分なサイズのバッファが確保されるようになります。
  4. それ以外の場合は、以前と同様に空文字列を返します。
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.hostnamekern.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システムコールが返したデータ長n0である場合の処理を修正しています。

  • 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.hostnamekern.domainnameの長さが常に...
  • // returned as 0 when a nil value is passed for oldp.: oldpnil値が渡されたときにゼロとして返されるというバグの具体的な内容を説明しています。
  • 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言語のソースコード (GitHub): https://github.com/golang/go
  • OpenBSDの公式ウェブサイト: https://www.openbsd.org/
  • sysctlに関する一般的な情報 (Wikipediaなど): https://ja.wikipedia.org/wiki/Sysctl
  • MAXHOSTNAMELENに関する情報 (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の要求時にoldpnil値が渡された場合、長さがゼロとして返される問題に対処しています。このケースに遭遇した場合、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.hostnamekern.domainnameといったシステム情報を取得する際に、sysctlシステムコールにoldp引数としてnil(またはNULLポインタ)を渡すと、期待されるデータ長ではなくゼロが返されるというバグがありました。通常、oldpnilを渡すのは、データの実際の長さを取得するためであり、その長さに基づいて適切なバッファを割り当ててから再度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のステップでoldpnilを渡した際に、kern.hostnamekern.domainnameの場合に限り、oldlenpに正しい長さではなくゼロが返されるというものでした。

kern.hostnamekern.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システムコールを呼び出した後、返された長さn0の場合、エラーではなく空文字列を返していました。これは、通常、データが存在しないか、取得できないことを意味します。

if n == 0 {
    return "", nil
}

しかし、OpenBSDのバグにより、kern.hostnamekern.domainnameの場合にoldpnilだと、データは存在するにもかかわらずn0と返されてしまう問題がありました。このため、GoのSysctl関数は、ホスト名やドメイン名を取得できないと誤って判断していました。

このコミットでは、このn == 0の条件に以下のワークアラウンドを追加しています。

  1. OS"openbsd"であるかを確認します。
  2. 取得しようとしているvalue"kern.hostname"または"kern.domainname"であるかを確認します。
  3. 上記の条件がすべて真である場合、nMAXHOSTNAMELEN(256)に設定します。これにより、後続の処理でホスト名またはドメイン名を格納するのに十分なサイズのバッファが確保されるようになります。
  4. それ以外の場合は、以前と同様に空文字列を返します。
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.hostnamekern.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システムコールが返したデータ長n0である場合の処理を修正しています。

  • 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.hostnamekern.domainnameの長さが常に...
  • // returned as 0 when a nil value is passed for oldp.: oldpnil値が渡されたときにゼロとして返されるというバグの具体的な内容を説明しています。
  • 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言語のソースコード (GitHub): https://github.com/golang/go
  • OpenBSDの公式ウェブサイト: https://www.openbsd.org/
  • sysctlに関する一般的な情報 (Wikipediaなど): https://ja.wikipedia.org/wiki/Sysctl
  • MAXHOSTNAMELENに関する情報 (Unix系システムのヘッダファイル): 通常、<sys/param.h><limits.h>などで定義されています。
  • OpenBSDの特定のsysctlバグに関する情報 (Web検索): "OpenBSD sysctl kern.hostname nil oldp bug" などのキーワードで検索しましたが、この特定のバグに関する直接的な公開情報は見つかりませんでした。これは、バグが非常に限定的であったか、あるいは修正がマイナーリリースに含まれたため、広く文書化されなかった可能性を示唆しています。