]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add padding to Linux kernel structures
authorRhys Hiltner <rhys@justin.tv>
Thu, 30 Sep 2021 00:35:27 +0000 (17:35 -0700)
committerIan Lance Taylor <iant@golang.org>
Tue, 2 Nov 2021 05:43:05 +0000 (05:43 +0000)
Go exchanges siginfo and sigevent structures with the kernel. They
contain unions, but Go's use is limited to the first few fields. Pad out
the rest so the size Go sees is the same as what the Linux kernel sees.

This is a follow-up to CL 342052 which added the sigevent struct without
padding, and to CL 353136 which added the padding but with an assertion
that confused several type-checkers. It updates the siginfo struct as
well so there are no bad examples in the defs_linux_*.go files.

Reviewed-on: https://go-review.googlesource.com/c/go/+/353136

Change-Id: I9610632ff0ec43eba91f560536f5441fa907b36f
Reviewed-on: https://go-review.googlesource.com/c/go/+/360094
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
13 files changed:
src/runtime/defs_linux_386.go
src/runtime/defs_linux_amd64.go
src/runtime/defs_linux_arm.go
src/runtime/defs_linux_arm64.go
src/runtime/defs_linux_mips64x.go
src/runtime/defs_linux_mipsx.go
src/runtime/defs_linux_ppc64.go
src/runtime/defs_linux_ppc64le.go
src/runtime/defs_linux_riscv64.go
src/runtime/defs_linux_s390x.go
src/runtime/export_linux_test.go
src/runtime/os_linux.go
src/runtime/runtime_linux_test.go

index d8b546cb4c7652a01f2e2a4011fcfc872e5169eb..24fb58bbf8db695eae5bf9c2bf0da4aae80c2c06 100644 (file)
@@ -3,6 +3,8 @@
 
 package runtime
 
+import "unsafe"
+
 const (
        _EINTR  = 0x4
        _EAGAIN = 0xb
@@ -166,7 +168,7 @@ type sigactiont struct {
        sa_mask     uint64
 }
 
-type siginfo struct {
+type siginfoFields struct {
        si_signo int32
        si_errno int32
        si_code  int32
@@ -174,6 +176,13 @@ type siginfo struct {
        si_addr uint32
 }
 
+type siginfo struct {
+       siginfoFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte
+}
+
 type stackt struct {
        ss_sp    *byte
        ss_flags int32
@@ -229,7 +238,7 @@ type itimerval struct {
        it_value    timeval
 }
 
-type sigevent struct {
+type sigeventFields struct {
        value  uintptr
        signo  int32
        notify int32
@@ -237,6 +246,13 @@ type sigevent struct {
        sigev_notify_thread_id int32
 }
 
+type sigevent struct {
+       sigeventFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte
+}
+
 type epollevent struct {
        events uint32
        data   [8]byte // to match amd64
index 6afb67f77f474c5bf696b35506fa41da472b99b1..36da22f8cedb78541dd89f4ea58d23f5831a8879 100644 (file)
@@ -3,6 +3,8 @@
 
 package runtime
 
+import "unsafe"
+
 const (
        _EINTR  = 0x4
        _EAGAIN = 0xb
@@ -128,7 +130,7 @@ type sigactiont struct {
        sa_mask     uint64
 }
 
-type siginfo struct {
+type siginfoFields struct {
        si_signo int32
        si_errno int32
        si_code  int32
@@ -136,6 +138,13 @@ type siginfo struct {
        si_addr uint64
 }
 
+type siginfo struct {
+       siginfoFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte
+}
+
 type itimerspec struct {
        it_interval timespec
        it_value    timespec
@@ -146,7 +155,7 @@ type itimerval struct {
        it_value    timeval
 }
 
-type sigevent struct {
+type sigeventFields struct {
        value  uintptr
        signo  int32
        notify int32
@@ -154,6 +163,13 @@ type sigevent struct {
        sigev_notify_thread_id int32
 }
 
+type sigevent struct {
+       sigeventFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte
+}
+
 type epollevent struct {
        events uint32
        data   [8]byte // unaligned uintptr
index ec24d76326e2fb3944fbd7f9cf89e333bc13a3d8..13d06969e3dea42123ac2cccac491eb9f9f361b0 100644 (file)
@@ -4,6 +4,8 @@
 
 package runtime
 
+import "unsafe"
+
 // Constants
 const (
        _EINTR  = 0x4
@@ -169,7 +171,7 @@ type itimerval struct {
        it_value    timeval
 }
 
-type sigevent struct {
+type sigeventFields struct {
        value  uintptr
        signo  int32
        notify int32
@@ -177,7 +179,14 @@ type sigevent struct {
        sigev_notify_thread_id int32
 }
 
-type siginfo struct {
+type sigevent struct {
+       sigeventFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte
+}
+
+type siginfoFields struct {
        si_signo int32
        si_errno int32
        si_code  int32
@@ -185,6 +194,13 @@ type siginfo struct {
        si_addr uint32
 }
 
+type siginfo struct {
+       siginfoFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte
+}
+
 type sigactiont struct {
        sa_handler  uintptr
        sa_flags    uint32
index f9f175004bc72adc6d03e9b8b728161c76ee441a..f9ee9cbc35aea63a1b26993ecedcccea6ec70175 100644 (file)
@@ -3,6 +3,8 @@
 
 package runtime
 
+import "unsafe"
+
 const (
        _EINTR  = 0x4
        _EAGAIN = 0xb
@@ -128,7 +130,7 @@ type sigactiont struct {
        sa_mask     uint64
 }
 
-type siginfo struct {
+type siginfoFields struct {
        si_signo int32
        si_errno int32
        si_code  int32
@@ -136,6 +138,13 @@ type siginfo struct {
        si_addr uint64
 }
 
+type siginfo struct {
+       siginfoFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte
+}
+
 type itimerspec struct {
        it_interval timespec
        it_value    timespec
@@ -146,7 +155,7 @@ type itimerval struct {
        it_value    timeval
 }
 
-type sigevent struct {
+type sigeventFields struct {
        value  uintptr
        signo  int32
        notify int32
@@ -154,6 +163,13 @@ type sigevent struct {
        sigev_notify_thread_id int32
 }
 
+type sigevent struct {
+       sigeventFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte
+}
+
 type epollevent struct {
        events uint32
        _pad   uint32
index 63433cb9be56bd502a1b57aa48e6d6e7bacf4609..2601082ee1aef7e39323bf07316bd84c06dab18e 100644 (file)
@@ -6,6 +6,8 @@
 
 package runtime
 
+import "unsafe"
+
 const (
        _EINTR  = 0x4
        _EAGAIN = 0xb
@@ -134,7 +136,7 @@ type sigactiont struct {
        sa_restorer uintptr
 }
 
-type siginfo struct {
+type siginfoFields struct {
        si_signo int32
        si_code  int32
        si_errno int32
@@ -143,6 +145,13 @@ type siginfo struct {
        si_addr uint64
 }
 
+type siginfo struct {
+       siginfoFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte
+}
+
 type itimerspec struct {
        it_interval timespec
        it_value    timespec
@@ -153,7 +162,7 @@ type itimerval struct {
        it_value    timeval
 }
 
-type sigevent struct {
+type sigeventFields struct {
        value  uintptr
        signo  int32
        notify int32
@@ -161,6 +170,13 @@ type sigevent struct {
        sigev_notify_thread_id int32
 }
 
+type sigevent struct {
+       sigeventFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte
+}
+
 type epollevent struct {
        events    uint32
        pad_cgo_0 [4]byte
index ffbf5051eba1ade4f9694009de1d6830eddb7c28..37651ef7e4330ebdd7086446e826b4e436e6bdd0 100644 (file)
@@ -6,6 +6,8 @@
 
 package runtime
 
+import "unsafe"
+
 const (
        _EINTR  = 0x4
        _EAGAIN = 0xb
@@ -129,7 +131,7 @@ type sigactiont struct {
        sa_restorer uintptr
 }
 
-type siginfo struct {
+type siginfoFields struct {
        si_signo int32
        si_code  int32
        si_errno int32
@@ -137,6 +139,13 @@ type siginfo struct {
        si_addr uint32
 }
 
+type siginfo struct {
+       siginfoFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte
+}
+
 type itimerspec struct {
        it_interval timespec
        it_value    timespec
@@ -147,7 +156,7 @@ type itimerval struct {
        it_value    timeval
 }
 
-type sigevent struct {
+type sigeventFields struct {
        value  uintptr
        signo  int32
        notify int32
@@ -155,6 +164,13 @@ type sigevent struct {
        sigev_notify_thread_id int32
 }
 
+type sigevent struct {
+       sigeventFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte
+}
+
 type epollevent struct {
        events    uint32
        pad_cgo_0 [4]byte
index e0775e297434bc1302390567fc49387657c03f64..c7aa7234c195551d588c33fe09f6493d1eed6703 100644 (file)
@@ -3,6 +3,8 @@
 
 package runtime
 
+import "unsafe"
+
 const (
        _EINTR  = 0x4
        _EAGAIN = 0xb
@@ -129,7 +131,7 @@ type sigactiont struct {
        sa_mask     uint64
 }
 
-type siginfo struct {
+type siginfoFields struct {
        si_signo int32
        si_errno int32
        si_code  int32
@@ -137,6 +139,13 @@ type siginfo struct {
        si_addr uint64
 }
 
+type siginfo struct {
+       siginfoFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte
+}
+
 type itimerspec struct {
        it_interval timespec
        it_value    timespec
@@ -147,7 +156,7 @@ type itimerval struct {
        it_value    timeval
 }
 
-type sigevent struct {
+type sigeventFields struct {
        value  uintptr
        signo  int32
        notify int32
@@ -155,6 +164,13 @@ type sigevent struct {
        sigev_notify_thread_id int32
 }
 
+type sigevent struct {
+       sigeventFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte
+}
+
 type epollevent struct {
        events    uint32
        pad_cgo_0 [4]byte
index e0775e297434bc1302390567fc49387657c03f64..c7aa7234c195551d588c33fe09f6493d1eed6703 100644 (file)
@@ -3,6 +3,8 @@
 
 package runtime
 
+import "unsafe"
+
 const (
        _EINTR  = 0x4
        _EAGAIN = 0xb
@@ -129,7 +131,7 @@ type sigactiont struct {
        sa_mask     uint64
 }
 
-type siginfo struct {
+type siginfoFields struct {
        si_signo int32
        si_errno int32
        si_code  int32
@@ -137,6 +139,13 @@ type siginfo struct {
        si_addr uint64
 }
 
+type siginfo struct {
+       siginfoFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte
+}
+
 type itimerspec struct {
        it_interval timespec
        it_value    timespec
@@ -147,7 +156,7 @@ type itimerval struct {
        it_value    timeval
 }
 
-type sigevent struct {
+type sigeventFields struct {
        value  uintptr
        signo  int32
        notify int32
@@ -155,6 +164,13 @@ type sigevent struct {
        sigev_notify_thread_id int32
 }
 
+type sigevent struct {
+       sigeventFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte
+}
+
 type epollevent struct {
        events    uint32
        pad_cgo_0 [4]byte
index 1052213a4c768483205f6cab987a390e6e5e38e5..332720a8c848d1d6f45ca23e930f196eb6a5bf81 100644 (file)
@@ -4,6 +4,8 @@
 
 package runtime
 
+import "unsafe"
+
 const (
        _EINTR  = 0x4
        _EAGAIN = 0xb
@@ -126,7 +128,7 @@ type sigactiont struct {
        sa_mask     uint64
 }
 
-type siginfo struct {
+type siginfoFields struct {
        si_signo int32
        si_errno int32
        si_code  int32
@@ -134,6 +136,13 @@ type siginfo struct {
        si_addr uint64
 }
 
+type siginfo struct {
+       siginfoFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte
+}
+
 type itimerspec struct {
        it_interval timespec
        it_value    timespec
@@ -144,7 +153,7 @@ type itimerval struct {
        it_value    timeval
 }
 
-type sigevent struct {
+type sigeventFields struct {
        value  uintptr
        signo  int32
        notify int32
@@ -152,6 +161,13 @@ type sigevent struct {
        sigev_notify_thread_id int32
 }
 
+type sigevent struct {
+       sigeventFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte
+}
+
 type epollevent struct {
        events    uint32
        pad_cgo_0 [4]byte
index b072955d4a3e2625ab08ae002d161f5fd0c41c38..740d8100c5dd449da5c6c5a43523cc7f598f5bef 100644 (file)
@@ -4,6 +4,8 @@
 
 package runtime
 
+import "unsafe"
+
 const (
        _EINTR  = 0x4
        _EAGAIN = 0xb
@@ -125,7 +127,7 @@ type sigactiont struct {
        sa_mask     uint64
 }
 
-type siginfo struct {
+type siginfoFields struct {
        si_signo int32
        si_errno int32
        si_code  int32
@@ -133,6 +135,13 @@ type siginfo struct {
        si_addr uint64
 }
 
+type siginfo struct {
+       siginfoFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_si_max_size - unsafe.Sizeof(siginfoFields{})]byte
+}
+
 type itimerspec struct {
        it_interval timespec
        it_value    timespec
@@ -143,7 +152,7 @@ type itimerval struct {
        it_value    timeval
 }
 
-type sigevent struct {
+type sigeventFields struct {
        value  uintptr
        signo  int32
        notify int32
@@ -151,6 +160,13 @@ type sigevent struct {
        sigev_notify_thread_id int32
 }
 
+type sigevent struct {
+       sigeventFields
+
+       // Pad struct to the max size in the kernel.
+       _ [_sigev_max_size - unsafe.Sizeof(sigeventFields{})]byte
+}
+
 type epollevent struct {
        events    uint32
        pad_cgo_0 [4]byte
index b7c901f238ff29479ef2f4c8fa3466e62540f0c2..dea94a934cef6665d72dff6cbfc1b02563f2874b 100644 (file)
@@ -8,11 +8,16 @@ package runtime
 
 import "unsafe"
 
+const SiginfoMaxSize = _si_max_size
+const SigeventMaxSize = _sigev_max_size
+
 var NewOSProc0 = newosproc0
 var Mincore = mincore
 var Add = add
 
 type EpollEvent epollevent
+type Siginfo siginfo
+type Sigevent sigevent
 
 func Epollctl(epfd, op, fd int32, ev unsafe.Pointer) int32 {
        return epollctl(epfd, op, fd, (*epollevent)(ev))
index 06773c21939404f28abc7140dd055064402edbda..32a1e1b4f7d9bc7c22e53d1a767b741c9e697dd5 100644 (file)
@@ -440,6 +440,11 @@ func pipe() (r, w int32, errno int32)
 func pipe2(flags int32) (r, w int32, errno int32)
 func setNonblock(fd int32)
 
+const (
+       _si_max_size    = 128
+       _sigev_max_size = 64
+)
+
 //go:nosplit
 //go:nowritebarrierrec
 func setsig(i uint32, fn uintptr) {
@@ -636,12 +641,11 @@ func setThreadCPUProfiler(hz int32) {
        spec.it_interval.setNsec(1e9 / int64(hz))
 
        var timerid int32
-       sevp := &sigevent{
-               notify:                 _SIGEV_THREAD_ID,
-               signo:                  _SIGPROF,
-               sigev_notify_thread_id: int32(mp.procid),
-       }
-       ret := timer_create(_CLOCK_THREAD_CPUTIME_ID, sevp, &timerid)
+       var sevp sigevent
+       sevp.notify = _SIGEV_THREAD_ID
+       sevp.signo = _SIGPROF
+       sevp.sigev_notify_thread_id = int32(mp.procid)
+       ret := timer_create(_CLOCK_THREAD_CPUTIME_ID, &sevp, &timerid)
        if ret != 0 {
                // If we cannot create a timer for this M, leave profileTimerValid false
                // to fall back to the process-wide setitimer profiler.
index cd59368cb2af4311ee0bca69cd64aade889350f9..a753aeea583d66e549faa192421f9134d5febc20 100644 (file)
@@ -61,3 +61,14 @@ func TestEpollctlErrorSign(t *testing.T) {
                t.Errorf("epollctl = %v, want %v", v, -EBADF)
        }
 }
+
+func TestKernelStructSize(t *testing.T) {
+       // Check that the Go definitions of structures exchanged with the kernel are
+       // the same size as what the kernel defines.
+       if have, want := unsafe.Sizeof(Siginfo{}), uintptr(SiginfoMaxSize); have != want {
+               t.Errorf("Go's siginfo struct is %d bytes long; kernel expects %d", have, want)
+       }
+       if have, want := unsafe.Sizeof(Sigevent{}), uintptr(SigeventMaxSize); have != want {
+               t.Errorf("Go's sigevent struct is %d bytes long; kernel expects %d", have, want)
+       }
+}