From 98c5dad5d1a0e8a73845ecc8897d0bd56586511d Mon Sep 17 00:00:00 2001 From: Gianguido Sora` Date: Mon, 6 Aug 2018 16:38:27 +0200 Subject: [PATCH] unix: update the OpenBSD pledge interface to handle execpromises The current Pledge function still takes into account the deprecated "paths" argument, which has been replaced by "execpromises". This change has been committed to OpenBSD on the 11 December 2017: https://marc.info/?l=openbsd-tech&m=151302727506669. This commit updates the Pledge function interface to reflect this change. Fixes golang/go#26824 Change-Id: Id6255b0432cf0a33e680e342dd23c7b02d0aa78f Reviewed-on: https://go-review.googlesource.com/127762 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- unix/openbsd_pledge.go | 75 +++++++++++++++++++++++++++++++++++++----- unix/openbsd_test.go | 2 +- 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/unix/openbsd_pledge.go b/unix/openbsd_pledge.go index 9b1e86a12..11388e5d4 100644 --- a/unix/openbsd_pledge.go +++ b/unix/openbsd_pledge.go @@ -8,6 +8,9 @@ package unix import ( + "errors" + "fmt" + "strconv" "syscall" "unsafe" ) @@ -16,23 +19,77 @@ const ( _SYS_PLEDGE = 108 ) -// Pledge implements the pledge syscall. For more information see pledge(2). -func Pledge(promises string, paths []string) error { - promisesPtr, err := syscall.BytePtrFromString(promises) +// Pledge implements the pledge syscall. +// +// The pledge syscall does not accept execpromises on OpenBSD releases +// before 6.3. +// +// execpromises must be empty when Pledge is called on OpenBSD +// releases predating 6.3, otherwise an error will be returned. +// +// For more information see pledge(2). +func Pledge(promises, execpromises string) error { + maj, min, err := majmin() if err != nil { return err } - promisesUnsafe, pathsUnsafe := unsafe.Pointer(promisesPtr), unsafe.Pointer(nil) - if paths != nil { - var pathsPtr []*byte - if pathsPtr, err = syscall.SlicePtrFromStrings(paths); err != nil { + + // If OpenBSD <= 5.9, pledge is not available. + if (maj == 5 && min != 9) || maj < 5 { + return fmt.Errorf("pledge syscall is not available on OpenBSD %d.%d", maj, min) + } + + // If OpenBSD <= 6.2 and execpromises is not empty + // return an error - execpromises is not available before 6.3 + if (maj < 6 || (maj == 6 && min <= 2)) && execpromises != "" { + return fmt.Errorf("cannot use execpromises on OpenBSD %d.%d", maj, min) + } + + pptr, err := syscall.BytePtrFromString(promises) + if err != nil { + return err + } + + // This variable will hold either a nil unsafe.Pointer or + // an unsafe.Pointer to a string (execpromises). + var expr unsafe.Pointer + + // If we're running on OpenBSD > 6.2, pass execpromises to the syscall. + if maj > 6 || (maj == 6 && min > 2) { + exptr, err := syscall.BytePtrFromString(execpromises) + if err != nil { return err } - pathsUnsafe = unsafe.Pointer(&pathsPtr[0]) + expr = unsafe.Pointer(exptr) } - _, _, e := syscall.Syscall(_SYS_PLEDGE, uintptr(promisesUnsafe), uintptr(pathsUnsafe), 0) + + _, _, e := syscall.Syscall(_SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0) if e != 0 { return e } + return nil } + +// majmin returns major and minor version number for an OpenBSD system. +func majmin() (major int, minor int, err error) { + var v Utsname + err = Uname(&v) + if err != nil { + return + } + + major, err = strconv.Atoi(string(v.Release[0])) + if err != nil { + err = errors.New("cannot parse major version number returned by uname") + return + } + + minor, err = strconv.Atoi(string(v.Release[2])) + if err != nil { + err = errors.New("cannot parse minor version number returned by uname") + return + } + + return +} diff --git a/unix/openbsd_test.go b/unix/openbsd_test.go index 734d76585..3ded96071 100644 --- a/unix/openbsd_test.go +++ b/unix/openbsd_test.go @@ -87,7 +87,7 @@ func TestMain(m *testing.M) { func init() { testProcs["pledge"] = testProc{ func() { - fmt.Println(unix.Pledge("", nil)) + fmt.Println(unix.Pledge("", "")) os.Exit(0) }, func() error {