[インデックス 13254] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおいて、Linux ARMアーキテクチャ向けのUID(ユーザーID)およびGID(グループID)関連のシステムコールが、古い16ビット版ではなく、新しい32ビット版を使用するように修正するものです。これにより、新しいLinuxカーネルでの互換性と堅牢性が向上します。
コミット
- コミットハッシュ: 911f802b37dec543caf7646fdc8987d4be299c5c
- Author: Shenghou Ma minux.ma@gmail.com
- Date: Sun Jun 3 06:49:57 2012 +0800
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/911f802b37dec543caf7646fdc8987d4be299c5c
元コミット内容
syscall: fix 32-bit uid calls
16-bit uid calls are not always supported in newer kernels.
R=dave, rsc, bradfitz
CC=golang-dev
https://golang.org/cl/6279047
変更の背景
この変更の背景には、LinuxカーネルにおけるUIDおよびGIDの扱いの進化があります。歴史的に、Linuxカーネル2.4より前では、UIDは16ビットの符号なし整数として表現されており、その範囲は0から65535に制限されていました。しかし、システムの規模が拡大するにつれて、この16ビットの制限では不十分となり、Linuxカーネル2.4で32ビットUIDのサポートが導入されました。これにより、UIDの範囲は0から4,294,967,295へと大幅に拡張されました。
この移行期間において、古い16ビットUIDを扱うシステムコールと、新しい32ビットUIDを扱うシステムコールが共存する形となりました。新しいカーネルでは、古い16ビット版のシステムコールが完全にサポートされない、あるいは非推奨となるケースが出てきました。Go言語のsyscall
パッケージは、OSのシステムコールを直接呼び出すためのインターフェースを提供しており、特定のアーキテクチャ(この場合はLinux ARM)において、古い16ビットUID関連のシステムコールを使用していると、新しいカーネル環境で問題が発生する可能性がありました。
このコミットは、このような互換性の問題を解決し、Goプログラムが新しいLinuxカーネル環境でもUID/GID関連の操作を正しく実行できるようにするために行われました。具体的には、chown
、fchown
、lchown
、getuid
、geteuid
、getgid
、getegid
、setuid
、setgid
、setreuid
、setregid
、setresuid
、setresgid
、setfsuid
、setfsgid
といったUID/GID関連のシステムコールを、明示的に32ビット版のシステムコール(例: SYS_CHOWN32
、SYS_GETUID32
など)に切り替えることで、将来的な互換性と堅牢性を確保しています。
前提知識の解説
UID (User ID) と GID (Group ID)
- UID (User ID): Linux/Unix系OSにおいて、システム上の各ユーザーを一意に識別するための数値です。ファイルやプロセスの所有権を管理するために使用されます。
- GID (Group ID): Linux/Unix系OSにおいて、ユーザーのグループを一意に識別するための数値です。複数のユーザーをまとめて管理し、ファイルやディレクトリへのアクセス権限をグループ単位で設定するために使用されます。
システムコール (Syscall)
システムコールは、ユーザー空間のプログラムがカーネル空間の機能(ファイルI/O、プロセス管理、メモリ管理など)にアクセスするためのインターフェースです。プログラムがOSの機能を利用する際には、直接ハードウェアを操作するのではなく、システムコールを介してカーネルに処理を依頼します。
16ビットUIDと32ビットUID
前述の通り、LinuxカーネルはUID/GIDの表現を16ビットから32ビットへと移行しました。
- 16ビットUID: 0から65535までの範囲のUIDを表現できます。古いシステムや組み込みシステムでよく見られます。
- 32ビットUID: 0から4,294,967,295までの範囲のUIDを表現できます。現代のLinuxシステムでは標準的に使用されており、より多くのユーザーやプロセスを扱う大規模システムに対応します。
この移行に伴い、カーネルは互換性を保つために、例えばsetuid()
(16ビット版)とsetuid32()
(32ビット版)のように、同じ機能を持つが引数のサイズが異なるシステムコールを提供しました。Cライブラリ(glibcなど)は、これらのカーネルレベルの違いを抽象化し、アプリケーションが透過的に適切なシステムコールを使用できるようにしています。
Go言語の syscall
パッケージ
Go言語のsyscall
パッケージは、OS固有のシステムコールへの低レベルなインターフェースを提供します。これにより、GoプログラムはOSの機能を直接利用できます。このパッケージは、異なるOSやアーキテクチャに対応するために、それぞれの環境に特化した実装を持っています。例えば、syscall_linux_arm.go
はLinux ARMアーキテクチャ向けのシステムコール定義を含んでいます。
//sys
ディレクティブは、Goのsyscall
パッケージがシステムコールを生成するための特別なコメントです。これによって、Goの関数が対応するCのシステムコールにマッピングされます。
技術的詳細
このコミットの技術的な核心は、Linux ARMアーキテクチャにおけるUID/GID関連のシステムコール呼び出しを、従来の16ビット版から32ビット版へと切り替える点にあります。
Linuxカーネルでは、UID/GIDを扱うシステムコールには、歴史的な経緯から16ビット版と32ビット版が存在します。例えば、ユーザーIDを変更するchown
システムコールには、古いSYS_CHOWN
(暗黙的に16ビットUIDを扱う可能性のあるもの)と、明示的に32ビットUIDを扱うSYS_CHOWN32
が存在します。新しいカーネルでは、SYS_CHOWN
のような汎用的なシステムコールが内部的に32ビットUIDを扱うようにリダイレクトされることもありますが、古いカーネルとの互換性や、特定のアーキテクチャ(ARMなど)での挙動の差異により、明示的に32ビット版のシステムコールを呼び出すことがより安全で堅牢な選択となります。
Goのsyscall
パッケージは、//sys
ディレクティブを使用して、Goの関数と対応するLinuxシステムコール番号をマッピングします。このコミットでは、このマッピングを変更し、SYS_CHOWN
のような汎用的なシステムコール番号ではなく、SYS_CHOWN32
のような明示的な32ビット版のシステムコール番号を使用するように修正しています。
具体的には、以下のシステムコールが32ビット版に切り替えられました。
Chown
->SYS_CHOWN32
Fchown
->SYS_FCHOWN32
Getegid
->SYS_GETEGID32
Geteuid
->SYS_GETEUID32
Getgid
->SYS_GETGID32
Getuid
->SYS_GETUID32
Lchown
->SYS_LCHOWN32
Setfsgid
->SYS_SETFSGID32
Setfsuid
->SYS_SETFSUID32
Setgid
->SYS_SETGID32
Setregid
->SYS_SETREGID32
Setresgid
->SYS_SETRESGID32
Setresuid
->SYS_SETRESUID32
Setreuid
->SYS_SETREUID32
これらの変更は、src/pkg/syscall/syscall_linux_arm.go
でシステムコール定義のマッピングを更新し、src/pkg/syscall/zsyscall_linux_arm.go
で実際にシステムコールを呼び出す部分の定数を変更することで実現されています。zsyscall_linux_arm.go
は通常、自動生成されるファイルであり、syscall_linux_arm.go
の定義に基づいて生成されます。したがって、syscall_linux_arm.go
の変更が根本的な修正となります。
この修正により、GoプログラムがLinux ARM環境でUID/GID関連の操作を行う際に、新しいカーネルの32ビットUID/GIDのセマンティクスに正しく準拠し、潜在的な互換性問題を回避できるようになります。
コアとなるコードの変更箇所
diff --git a/src/pkg/syscall/syscall_linux_arm.go b/src/pkg/syscall/syscall_linux_arm.go
index 48b5d31d74..2f29079453 100644
--- a/src/pkg/syscall/syscall_linux_arm.go
+++ b/src/pkg/syscall/syscall_linux_arm.go
@@ -41,26 +41,28 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error)
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
//sys sendmsg(s int, msg *Msghdr, flags int) (err error)
-//sys Chown(path string, uid int, gid int) (err error)
-//sys Fchown(fd int, uid int, gid int) (err error)
+// 64-bit file system and 32-bit uid calls
+// (16-bit uid calls are not always supported in newer kernels)
+//sys Chown(path string, uid int, gid int) (err error) = SYS_CHOWN32
+//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatfs(fd int, buf *Statfs_t) (err error) = SYS_FSTATFS64
-//sysnb Getegid() (egid int)
-//sysnb Geteuid() (euid int)
-//sysnb Getgid() (gid int)
-//sysnb Getuid() (uid int)
-//sys Lchown(path string, uid int, gid int) (err error)
+//sysnb Getegid() (egid int) = SYS_GETEGID32
+//sysnb Geteuid() (euid int) = SYS_GETEUID32
+//sysnb Getgid() (gid int) = SYS_GETGID32
+//sysnb Getuid() (uid int) = SYS_GETUID32
+//sys Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32
//sys Listen(s int, n int) (err error)
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
-//sys Setfsgid(gid int) (err error)
-//sys Setfsuid(uid int) (err error)
-//sysnb Setgid(gid int) (err error)
-//sysnb Setregid(rgid int, egid int) (err error)
-//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
-//sysnb Setresuid(ruid int, euid int, suid int) (err error)
-//sysnb Setreuid(ruid int, euid int) (err error)
+//sys Setfsgid(gid int) (err error) = SYS_SETFSGID32
+//sys Setfsuid(uid int) (err error) = SYS_SETFSUid32
+//sysnb Setgid(gid int) (err error) = SYS_SETGID32
+//sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32
+//sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32
+//sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32
+//sysnb Setreuid(ruid int, euid int) (err error) = SYS_SETREUID32
//sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error)
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
diff --git a/src/pkg/syscall/zsyscall_linux_arm.go b/src/pkg/syscall/zsyscall_linux_arm.go
index 1e86d3b7f1..b1a59a69ea 100644
--- a/src/pkg/syscall/zsyscall_linux_arm.go
+++ b/src/pkg/syscall/zsyscall_linux_arm.go
@@ -1203,7 +1203,7 @@ func sendmsg(s int, msg *Msghdr, flags int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Chown(path string, uid int, gid int) (err error) {
- _, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))\n+\t_, _, e1 := Syscall(SYS_CHOWN32, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))\n \tif e1 != 0 {\n \t\terr = e1\n \t}\n@@ -1213,7 +1213,7 @@ func Chown(path string, uid int, gid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Fchown(fd int, uid int, gid int) (err error) {
-\t_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))\n+\t_, _, e1 := Syscall(SYS_FCHOWN32, uintptr(fd), uintptr(uid), uintptr(gid))\n \tif e1 != 0 {\n \t\terr = e1\n \t}\n@@ -1243,7 +1243,7 @@ func Fstatfs(fd int, buf *Statfs_t) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getegid() (egid int) {
-\tr0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0)\n+\tr0, _, _ := RawSyscall(SYS_GETEGID32, 0, 0, 0)\n \tegid = int(r0)\n \treturn\n }\n@@ -1251,7 +1251,7 @@ func Getegid() (egid int) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Geteuid() (euid int) {
-\tr0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0)\n+\tr0, _, _ := RawSyscall(SYS_GETEUID32, 0, 0, 0)\n \teuid = int(r0)\n \treturn\n }\n@@ -1259,7 +1259,7 @@ func Geteuid() (euid int) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getgid() (gid int) {
-\tr0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0)\n+\tr0, _, _ := RawSyscall(SYS_GETGID32, 0, 0, 0)\n \tgid = int(r0)\n \treturn\n }\n@@ -1267,7 +1267,7 @@ func Getgid() (gid int) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Getuid() (uid int) {
-\tr0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)\n+\tr0, _, _ := RawSyscall(SYS_GETUID32, 0, 0, 0)\n \tuid = int(r0)\n \treturn\n }\n@@ -1275,7 +1275,7 @@ func Getuid() (uid int) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Lchown(path string, uid int, gid int) (err error) {
-\t_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))\n+\t_, _, e1 := Syscall(SYS_LCHOWN32, uintptr(unsafe.Pointer(StringBytePtr(path))), uintptr(uid), uintptr(gid))\n \tif e1 != 0 {\n \t\terr = e1\n \t}\n@@ -1327,7 +1327,7 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setfsgid(gid int) (err error) {
-\t_, _, e1 := Syscall(SYS_SETFSGID, uintptr(gid), 0, 0)\n+\t_, _, e1 := Syscall(SYS_SETFSGID32, uintptr(gid), 0, 0)\n \tif e1 != 0 {\n \t\terr = e1\n \t}\n@@ -1337,7 +1337,7 @@ func Setfsgid(gid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setfsuid(uid int) (err error) {
-\t_, _, e1 := Syscall(SYS_SETFSUID, uintptr(uid), 0, 0)\n+\t_, _, e1 := Syscall(SYS_SETFSUID32, uintptr(uid), 0, 0)\n \tif e1 != 0 {\n \t\terr = e1\n \t}\n@@ -1347,7 +1347,7 @@ func Setfsuid(uid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setgid(gid int) (err error) {
-\t_, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0)\n+\t_, _, e1 := RawSyscall(SYS_SETGID32, uintptr(gid), 0, 0)\n \tif e1 != 0 {\n \t\terr = e1\n \t}\n@@ -1357,7 +1357,7 @@ func Setgid(gid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setregid(rgid int, egid int) (err error) {
-\t_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)\n+\t_, _, e1 := RawSyscall(SYS_SETREGID32, uintptr(rgid), uintptr(egid), 0)\n \tif e1 != 0 {\n \t\terr = e1\n \t}\n@@ -1367,7 +1367,7 @@ func Setregid(rgid int, egid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setresgid(rgid int, egid int, sgid int) (err error) {
-\t_, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid))\n+\t_, _, e1 := RawSyscall(SYS_SETRESGID32, uintptr(rgid), uintptr(egid), uintptr(sgid))\n \tif e1 != 0 {\n \t\terr = e1\n \t}\n@@ -1377,7 +1377,7 @@ func Setresgid(rgid int, egid int, sgid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setresuid(ruid int, euid int, suid int) (err error) {
-\t_, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid))\n+\t_, _, e1 := RawSyscall(SYS_SETRESUID32, uintptr(ruid), uintptr(euid), uintptr(suid))\n \tif e1 != 0 {\n \t\terr = e1\n \t}\n@@ -1387,7 +1387,7 @@ func Setresuid(ruid int, euid int, suid int) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Setreuid(ruid int, euid int) (err error) {
-\t_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)\n+\t_, _, e1 := RawSyscall(SYS_SETREUID32, uintptr(ruid), uintptr(euid), 0)\n \tif e1 != 0 {\n \t\terr = e1\n \t}\n```
## コアとなるコードの解説
このコミットは主に2つのファイルに影響を与えています。
1. **`src/pkg/syscall/syscall_linux_arm.go`**:
このファイルは、Goの`syscall`パッケージがLinux ARMアーキテクチャ向けに提供するシステムコール関数の定義を含んでいます。変更点を見ると、`//sys`ディレクティブで定義されている各UID/GID関連のシステムコール(例: `Chown`, `Fchown`, `Getegid`など)に対して、明示的に32ビット版のシステムコール番号(例: `= SYS_CHOWN32`)が追加されています。
コメント`// 64-bit file system and 32-bit uid calls (16-bit uid calls are not always supported in newer kernels)`が追加されており、この変更の意図が明確に示されています。これは、ファイルシステム関連のシステムコールが64ビットに対応しているのと同様に、UID関連のシステムコールも32ビットに対応させるべきであり、古い16ビット版は新しいカーネルでは常にサポートされるとは限らない、という認識に基づいています。
2. **`src/pkg/syscall/zsyscall_linux_arm.go`**:
このファイルは、`syscall_linux_arm.go`の定義に基づいて自動生成されるファイルです。Goのシステムコール関数が実際にカーネルのシステムコールを呼び出す際の、具体的なシステムコール番号(`SYS_CHOWN`など)が記述されています。
このコミットでは、`Chown`関数が`Syscall(SYS_CHOWN, ...)`から`Syscall(SYS_CHOWN32, ...)`へと変更されているように、各UID/GID関連の関数が呼び出すシステムコール番号が、対応する32ビット版の定数に置き換えられています。例えば、`Getuid()`関数は`RawSyscall(SYS_GETUID, ...)`から`RawSyscall(SYS_GETUID32, ...)`に変更されています。
この変更は、`syscall_linux_arm.go`での定義変更が反映された結果であり、Goプログラムが実際に実行時に呼び出すシステムコールが、意図通り32ビット版になることを保証します。
これらの変更により、Go言語で書かれたプログラムがLinux ARM環境でUID/GIDを操作する際に、より新しいカーネルのセマンティクスに準拠し、潜在的な互換性問題を回避できるようになります。
## 関連リンク
* Go CL 6279047: [https://golang.org/cl/6279047](https://golang.org/cl/6279047)
## 参考にした情報源リンク
* Linux kernel 16-bit uid 32-bit uid syscallsに関するWeb検索結果
* systemd.io (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGTHhdmhL1PF6PqpmERgUZ_izryWQ8-CdFjCZac6hYIC2XzYoRWHPUJnkOAt6KjcTNQDfrrlqmmxNMKZ1lhAOUZ580z3G0lzw2lTF9gUiMQZj4FyPsFqO8a)
* kernel.org (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEQe4NCr93wVijuy_uYqJyh8EavVCtRZC3Q6cMtz9tPdAMMwmpU2VHzCmqkQpdxlN0uDuEMAwpU_AIEfNToAthFj1UwBaB7zAy-lZC2F8kGgQSRU8u6o-5kMJbODdBugN9FBoXXYZq9JaUf9FucLh89bHb0KH6R6T0=)
* man7.org (setuid): (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQH2pde8nfU_5n3AZjSBrjCsZaGSL0jtc_MKTAf82k6gd_8kjjssTKYoY04iN8Stt4NXn6E7je8eNXrb1DyudmJdZ9rMZ2RI5w5TgkFA1uGd5hTyuNUkzGtJ7AKH6uMv6n8pXrFRvqfO29XFhSHFJg==)
* man7.org (setfsuid): (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQG88AqM0sAKloIKMjpj-4OKukGPtWhEi-ibyRzyb4_s-etpq79CsOyWAWhywSCwvqoj_p_cBk2fifmdoXYU3x-BnXgBs_mXMQcSUYhL37EGfPjSIwgkNe8e4ICB4Squz26dYW76_HqehMgJbcHKg9t3)
* infradead.org (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFfSSmqt1zeRC0cuQHxnKxOKa708LoF0IcPYLL68hP97hxbFXPlL9-prH5Ize9MbqnNaxFToxPgy_O2Ju95O154bIk_z3y_vuDXUI5zgJ9ispl0STNLEMh2OzAwlNih7zHsy-4Hj1wAvDvuOnOb92KrkFjYQxk4KGhICqmHSE0FOXoG0rWoy5-VRGva)
* man7.org (UID types): (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFiq2DWJUKjfeNlABeESIK5gciQv1Cc3GjAiEMaGg89vBuPqGL8cIxn8RvgN8wUsHhFozkDXNjLj0Y-Z78HowVlAwvnV0NiNfHgMIfDxrFJkgTSFd4xlG1G4xU2v_-bzzYDLPW0JD5A1SC2-pIA4gy-Q6zQ)