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

[インデックス 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関連の操作を正しく実行できるようにするために行われました。具体的には、chownfchownlchowngetuidgeteuidgetgidgetegidsetuidsetgidsetreuidsetregidsetresuidsetresgidsetfsuidsetfsgidといったUID/GID関連のシステムコールを、明示的に32ビット版のシステムコール(例: SYS_CHOWN32SYS_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)