blob: 8a9c87995653b525946462be8de4dfe008a5582a [file] [log] [blame]
Serge Bazanskicc25bdf2018-10-25 14:02:58 +02001// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// +build openbsd
6// +build 386 amd64 arm
7
8package unix
9
10import (
11 "errors"
12 "fmt"
13 "strconv"
14 "syscall"
15 "unsafe"
16)
17
18// Pledge implements the pledge syscall.
19//
20// The pledge syscall does not accept execpromises on OpenBSD releases
21// before 6.3.
22//
23// execpromises must be empty when Pledge is called on OpenBSD
24// releases predating 6.3, otherwise an error will be returned.
25//
26// For more information see pledge(2).
27func Pledge(promises, execpromises string) error {
28 maj, min, err := majmin()
29 if err != nil {
30 return err
31 }
32
33 // If OpenBSD <= 5.9, pledge is not available.
34 if (maj == 5 && min != 9) || maj < 5 {
35 return fmt.Errorf("pledge syscall is not available on OpenBSD %d.%d", maj, min)
36 }
37
38 // If OpenBSD <= 6.2 and execpromises is not empty
39 // return an error - execpromises is not available before 6.3
40 if (maj < 6 || (maj == 6 && min <= 2)) && execpromises != "" {
41 return fmt.Errorf("cannot use execpromises on OpenBSD %d.%d", maj, min)
42 }
43
44 pptr, err := syscall.BytePtrFromString(promises)
45 if err != nil {
46 return err
47 }
48
49 // This variable will hold either a nil unsafe.Pointer or
50 // an unsafe.Pointer to a string (execpromises).
51 var expr unsafe.Pointer
52
53 // If we're running on OpenBSD > 6.2, pass execpromises to the syscall.
54 if maj > 6 || (maj == 6 && min > 2) {
55 exptr, err := syscall.BytePtrFromString(execpromises)
56 if err != nil {
57 return err
58 }
59 expr = unsafe.Pointer(exptr)
60 }
61
62 _, _, e := syscall.Syscall(SYS_PLEDGE, uintptr(unsafe.Pointer(pptr)), uintptr(expr), 0)
63 if e != 0 {
64 return e
65 }
66
67 return nil
68}
69
70// majmin returns major and minor version number for an OpenBSD system.
71func majmin() (major int, minor int, err error) {
72 var v Utsname
73 err = Uname(&v)
74 if err != nil {
75 return
76 }
77
78 major, err = strconv.Atoi(string(v.Release[0]))
79 if err != nil {
80 err = errors.New("cannot parse major version number returned by uname")
81 return
82 }
83
84 minor, err = strconv.Atoi(string(v.Release[2]))
85 if err != nil {
86 err = errors.New("cannot parse minor version number returned by uname")
87 return
88 }
89
90 return
91}