Skip to content

Commit

Permalink
unix: update the OpenBSD pledge interface to handle execpromises
Browse files Browse the repository at this point in the history
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 <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
  • Loading branch information
gsora authored and ianlancetaylor committed Aug 10, 2018
1 parent f0d5e33 commit 98c5dad
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 10 deletions.
75 changes: 66 additions & 9 deletions unix/openbsd_pledge.go
Expand Up @@ -8,6 +8,9 @@
package unix

import (
"errors"
"fmt"
"strconv"
"syscall"
"unsafe"
)
Expand All @@ -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
}
2 changes: 1 addition & 1 deletion unix/openbsd_test.go
Expand Up @@ -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 {
Expand Down

0 comments on commit 98c5dad

Please sign in to comment.