runtime: add padding to Linux kernel structures

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>
This commit is contained in:
Rhys Hiltner 2021-09-29 17:35:27 -07:00 committed by Ian Lance Taylor
parent 6f327f7b88
commit a97c527ac4
13 changed files with 206 additions and 26 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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))

View 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.

View 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)
}
}