Skip to content

Commit

Permalink
Backport CVE-2023-29403 fix to 1.18
Browse files Browse the repository at this point in the history
  • Loading branch information
derekparker committed Aug 4, 2023
1 parent 8828e24 commit 40272cb
Show file tree
Hide file tree
Showing 48 changed files with 659 additions and 5 deletions.
19 changes: 19 additions & 0 deletions src/runtime/extern.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,25 @@ the set of Go environment variables. They influence the building of Go programs
GOARCH, GOOS, and GOROOT are recorded at compile time and made available by
constants or functions in this package, but they do not influence the execution
of the run-time system.
# Security
On Unix platforms, Go's runtime system behaves slightly differently when a
binary is setuid/setgid or executed with setuid/setgid-like properties, in order
to prevent dangerous behaviors. On Linux this is determined by checking for the
AT_SECURE flag in the auxiliary vector, on the BSDs and Solaris/Illumos it is
determined by checking the issetugid syscall, and on AIX it is determined by
checking if the uid/gid match the effective uid/gid.
When the runtime determines the binary is setuid/setgid-like, it does three main
things:
- The standard input/output file descriptors (0, 1, 2) are checked to be open.
If any of them are closed, they are opened pointing at /dev/null.
- The value of the GOTRACEBACK environment variable is set to 'none'.
- When a signal is received that terminates the program, or the program
encounters an unrecoverable panic that would otherwise override the value
of GOTRACEBACK, the goroutine stack, registers, and other memory related
information are omitted.
*/
package runtime

Expand Down
9 changes: 9 additions & 0 deletions src/runtime/internal/syscall/defs_linux_386.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package syscall

const (
SYS_FCNTL = 55
)
9 changes: 9 additions & 0 deletions src/runtime/internal/syscall/defs_linux_amd64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package syscall

const (
SYS_FCNTL = 72
)
9 changes: 9 additions & 0 deletions src/runtime/internal/syscall/defs_linux_arm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package syscall

const (
SYS_FCNTL = 55
)
9 changes: 9 additions & 0 deletions src/runtime/internal/syscall/defs_linux_arm64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package syscall

const (
SYS_FCNTL = 25
)
11 changes: 11 additions & 0 deletions src/runtime/internal/syscall/defs_linux_mips64x.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build linux && (mips64 || mips64le)

package syscall

const (
SYS_FCNTL = 5070
)
11 changes: 11 additions & 0 deletions src/runtime/internal/syscall/defs_linux_mipsx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build linux && (mips || mipsle)

package syscall

const (
SYS_FCNTL = 4055
)
11 changes: 11 additions & 0 deletions src/runtime/internal/syscall/defs_linux_ppc64x.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build linux && (ppc64 || ppc64le)

package syscall

const (
SYS_FCNTL = 55
)
9 changes: 9 additions & 0 deletions src/runtime/internal/syscall/defs_linux_riscv64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package syscall

const (
SYS_FCNTL = 25
)
9 changes: 9 additions & 0 deletions src/runtime/internal/syscall/defs_linux_s390x.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package syscall

const (
SYS_FCNTL = 55
)
12 changes: 12 additions & 0 deletions src/runtime/os2_aix.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ var (
//go:cgo_import_dynamic libc_sysconf sysconf "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_usleep usleep "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_write write "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_getuid getuid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_geteuid geteuid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_getgid getgid "libc.a/shr_64.o"
//go:cgo_import_dynamic libc_getegid getegid "libc.a/shr_64.o"

//go:cgo_import_dynamic libpthread___pth_init __pth_init "libpthread.a/shr_xpg5_64.o"
//go:cgo_import_dynamic libpthread_attr_destroy pthread_attr_destroy "libpthread.a/shr_xpg5_64.o"
Expand Down Expand Up @@ -95,6 +99,10 @@ var (
//go:linkname libc_sysconf libc_sysconf
//go:linkname libc_usleep libc_usleep
//go:linkname libc_write libc_write
//go:linkname libc_getuid libc_getuid
//go:linkname libc_geteuid libc_geteuid
//go:linkname libc_getgid libc_getgid
//go:linkname libc_getegid libc_getegid

//go:linkname libpthread___pth_init libpthread___pth_init
//go:linkname libpthread_attr_destroy libpthread_attr_destroy
Expand Down Expand Up @@ -137,6 +145,10 @@ var (
libc_sysconf,
libc_usleep,
libc_write,
libc_getuid,
libc_geteuid,
libc_getgid,
libc_getegid,
//libpthread
libpthread___pth_init,
libpthread_attr_destroy,
Expand Down
40 changes: 40 additions & 0 deletions src/runtime/os_aix.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,3 +383,43 @@ const sigPerThreadSyscall = 1 << 31
func runPerThreadSyscall() {
throw("runPerThreadSyscall only valid on linux")
}

//go:nosplit
func getuid() int32 {
r, errno := syscall0(&libc_getuid)
if errno != 0 {
print("getuid failed ", errno)
throw("getuid")
}
return int32(r)
}

//go:nosplit
func geteuid() int32 {
r, errno := syscall0(&libc_geteuid)
if errno != 0 {
print("geteuid failed ", errno)
throw("geteuid")
}
return int32(r)
}

//go:nosplit
func getgid() int32 {
r, errno := syscall0(&libc_getgid)
if errno != 0 {
print("getgid failed ", errno)
throw("getgid")
}
return int32(r)
}

//go:nosplit
func getegid() int32 {
r, errno := syscall0(&libc_getegid)
if errno != 0 {
print("getegid failed ", errno)
throw("getegid")
}
return int32(r)
}
2 changes: 2 additions & 0 deletions src/runtime/os_dragonfly.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ func pipe2(flags int32) (r, w int32, errno int32)
func closeonexec(fd int32)
func setNonblock(fd int32)

func issetugid() int32

// From DragonFly's <sys/sysctl.h>
const (
_CTL_HW = 6
Expand Down
2 changes: 2 additions & 0 deletions src/runtime/os_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ func pipe2(flags int32) (r, w int32, errno int32)
func closeonexec(fd int32)
func setNonblock(fd int32)

func issetugid() int32

// From FreeBSD's <sys/sysctl.h>
const (
_CTL_HW = 6
Expand Down
25 changes: 25 additions & 0 deletions src/runtime/os_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,12 @@ const (
)

// Atomically,
//
// if(*addr == val) sleep
//
// Might be woken up spuriously; that's allowed.
// Don't sleep longer than ns; ns < 0 means forever.
//
//go:nosplit
func futexsleep(addr *uint32, val uint32, ns int64) {
// Some Linux kernels have a bug where futex of
Expand All @@ -73,6 +76,7 @@ func futexsleep(addr *uint32, val uint32, ns int64) {
}

// If any procs are sleeping on addr, wake up at most cnt.
//
//go:nosplit
func futexwakeup(addr *uint32, cnt uint32) {
ret := futex(unsafe.Pointer(addr), _FUTEX_WAKE_PRIVATE, cnt, nil, nil, 0)
Expand Down Expand Up @@ -157,6 +161,7 @@ const (
func clone(flags int32, stk, mp, gp, fn unsafe.Pointer) int32

// May run with m.p==nil, so write barriers are not allowed.
//
//go:nowritebarrier
func newosproc(mp *m) {
stk := unsafe.Pointer(mp.g0.stack.hi)
Expand Down Expand Up @@ -184,6 +189,7 @@ func newosproc(mp *m) {
}

// Version of newosproc that doesn't require a valid G.
//
//go:nosplit
func newosproc0(stacksize uintptr, fn unsafe.Pointer) {
stack := sysAlloc(stacksize, &memstats.stacks_sys)
Expand All @@ -205,6 +211,7 @@ const (
_AT_NULL = 0 // End of vector
_AT_PAGESZ = 6 // System physical page size
_AT_HWCAP = 16 // hardware capability bit vector
_AT_SECURE = 23 // secure mode boolean
_AT_RANDOM = 25 // introduced in 2.6.29
_AT_HWCAP2 = 26 // hardware capability bit vector 2
)
Expand Down Expand Up @@ -274,6 +281,9 @@ func sysargs(argc int32, argv **byte) {
// the ELF AT_RANDOM auxiliary vector.
var startupRandomData []byte

// secureMode holds the value of AT_SECURE passed in the auxiliary vector.
var secureMode bool

func sysauxv(auxv []uintptr) int {
var i int
for ; auxv[i] != _AT_NULL; i += 2 {
Expand All @@ -286,6 +296,9 @@ func sysauxv(auxv []uintptr) int {

case _AT_PAGESZ:
physPageSize = val

case _AT_SECURE:
secureMode = val == 1
}

archauxv(tag, val)
Expand Down Expand Up @@ -365,6 +378,7 @@ func goenvs() {
// Called to do synchronous initialization of Go code built with
// -buildmode=c-archive or -buildmode=c-shared.
// None of the Go runtime is initialized.
//
//go:nosplit
//go:nowritebarrierrec
func libpreinit() {
Expand Down Expand Up @@ -392,6 +406,7 @@ func minit() {
}

// Called from dropm to undo the effect of an minit.
//
//go:nosplit
func unminit() {
unminitSignals()
Expand Down Expand Up @@ -450,6 +465,12 @@ func pipe() (r, w int32, errno int32)
func pipe2(flags int32) (r, w int32, errno int32)
func setNonblock(fd int32)

//go:nosplit
func fcntl(fd, cmd, arg int32) (ret int32, errno int32) {
r, _, err := syscall.Syscall6(syscall.SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg), 0, 0, 0)
return int32(r), int32(err)
}

const (
_si_max_size = 128
_sigev_max_size = 64
Expand Down Expand Up @@ -499,6 +520,7 @@ func getsig(i uint32) uintptr {
}

// setSignaltstackSP sets the ss_sp field of a stackt.
//
//go:nosplit
func setSignalstackSP(s *stackt, sp uintptr) {
*(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp
Expand All @@ -509,6 +531,7 @@ func (c *sigctxt) fixsigcode(sig uint32) {
}

// sysSigaction calls the rt_sigaction system call.
//
//go:nosplit
func sysSigaction(sig uint32, new, old *sigactiont) {
if rt_sigaction(uintptr(sig), new, old, unsafe.Sizeof(sigactiont{}.sa_mask)) != 0 {
Expand All @@ -533,6 +556,7 @@ func sysSigaction(sig uint32, new, old *sigactiont) {
}

// rt_sigaction is implemented in assembly.
//
//go:noescape
func rt_sigaction(sig uintptr, new, old *sigactiont, size uintptr) int32

Expand Down Expand Up @@ -855,6 +879,7 @@ func syscall_runtime_doAllThreadsSyscall(trap, a1, a2, a3, a4, a5, a6 uintptr) (
//
// This function throws if the system call returns with anything other than the
// expected values.
//
//go:nosplit
func runPerThreadSyscall() {
gp := getg()
Expand Down
2 changes: 2 additions & 0 deletions src/runtime/os_netbsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ func pipe2(flags int32) (r, w int32, errno int32)
func closeonexec(fd int32)
func setNonblock(fd int32)

func issetugid() int32

const (
_ESRCH = 3
_ETIMEDOUT = 60
Expand Down
2 changes: 2 additions & 0 deletions src/runtime/os_openbsd_syscall2.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,5 @@ func closeonexec(fd int32)
func setNonblock(fd int32)

func walltime() (sec int64, nsec int32)

func issetugid() int32
4 changes: 4 additions & 0 deletions src/runtime/os_solaris.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,7 @@ func sysvicall6(fn *libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
}
return libcall.r1
}

func issetugid() int32 {
return int32(sysvicall0(&libc_issetugid))
}
4 changes: 4 additions & 0 deletions src/runtime/panic.go
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,10 @@ func fatalthrow() {
// Switch to the system stack to avoid any stack growth, which
// may make things worse if the runtime is in a bad state.
systemstack(func() {
if isSecureMode() {
exit(2)
}

startpanic_m()

if dopanic_m(gp, pc, sp) {
Expand Down
1 change: 1 addition & 0 deletions src/runtime/proc.go
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ func schedinit() {

goargs()
goenvs()
secure()
parsedebugvars()
gcinit()

Expand Down
Loading

0 comments on commit 40272cb

Please sign in to comment.